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 {
242 return value[
static_cast<
int>(i)];
248
249
253constexpr int distinct_attempt_multiplier = 84;
258template <
typename Seen,
typename Fn>
259auto try_generate_distinct(Seen &seen, Fn &&next,
bool insert =
true)
260 -> std::optional<std::invoke_result_t<Fn &>> {
261 using T = std::invoke_result_t<Fn &>;
263 distinct_attempt_multiplier * std::max<size_t>(1, seen.size());
264 for (size_t i = 0; i < attempts; ++i) {
267 if (seen.insert(val).second)
269 }
else if (seen.count(val) == 0)
278
279
282enum class compiler_kind { gcc, clang, unknown };
290 compiler_value(compiler_kind kind = compiler_kind::unknown,
int major = 0,
292 : kind_(kind), major_(major), minor_(minor) {}
301 cpp_value(std::optional<
int> version = std::nullopt)
302 : version_(version ? *version : 0) {
304 tgen_ensure(*version == 17
or *version == 20
or *version == 23,
305 "unsupported C++ version (use 17, 20, 23)");
316
317
320template <
typename T>
struct list;
323template <
typename Func,
typename... Args>
struct distinct {
325 std::tuple<Args...> args_;
330 : func_(std::move(func)), args_(std::move(args)...) {}
352 auto val = generate_distinct(
true);
356 throw detail::error(
"distinct: no more distinct values");
358 template <
typename U>
auto gen(std::initializer_list<U> il) {
359 return gen(std::vector<U>(il));
365 for (
int i = 0; i < size; ++i)
366 res.push_back(gen());
368 return typename list<T>::value(res);
374 bool empty() {
return generate_distinct(
false) == std::nullopt; }
380 auto val = generate_distinct(
true);
386 return typename list<T>::value(res);
390 friend std::ostream &operator<<(std::ostream &out,
const distinct &) {
392 detail::dependent_false_v<
distinct>,
393 "distinct: cannot print a distinct generator. Maybe you forgot to "
401 auto generate_distinct(
bool insert) {
402 return detail::try_generate_distinct(
403 seen_, [&] {
return std::apply(func_, args_); }, insert);
406template <
typename Func,
typename... Args>
407distinct(Func, Args...) ->
distinct<Func, Args...>;
411 const Gen &self()
const {
return *
static_cast<
const Gen *>(
this); }
413 template <
typename... Args>
auto gen_list(
int size, Args &&...args)
const {
414 std::vector<
typename Gen::value> res;
416 for (
int i = 0; i < size; ++i)
417 res.push_back(
static_cast<
const Gen *>(
this)->gen(
418 std::forward<Args>(args)...));
420 return typename list<
typename Gen::value>::value(res);
424 template <
typename Pred,
typename... Args>
425 auto gen_until(Pred predicate,
int max_tries, Args &&...args)
const {
426 for (
int i = 0; i < max_tries; ++i) {
427 typename Gen::value val =
static_cast<
const Gen *>(
this)->gen(
428 std::forward<Args>(args)...);
434 throw detail::error(
"could not generate value matching predicate");
436 template <
typename Pred,
typename T,
typename... Args>
437 auto gen_until(Pred predicate,
int max_tries, std::initializer_list<T> il,
438 Args &&...args)
const {
439 return gen_until(predicate, max_tries, std::vector<T>(il),
440 std::forward<Args>(args)...);
444 template <
typename... Args>
auto distinct(Args &&...args)
const {
446 [self = self()](
auto &&...inner_args)
mutable ->
decltype(
auto) {
448 std::forward<
decltype(inner_args)>(inner_args)...);
450 std::forward<Args>(args)...);
452 template <
typename T,
typename... Args>
453 auto distinct(std::initializer_list<T> il, Args &&...args)
const {
454 return distinct(std::vector<T>(il), std::forward<Args>(args)...);
458 friend std::ostream &operator<<(std::ostream &out,
const gen_base &) {
459 static_assert(detail::dependent_false_v<
gen_base>,
460 "gen_base: cannot print a generator. Maybe you forgot to "
468 const Val &self()
const {
return *
static_cast<
const Val *>(
this); }
471 return self().to_std() < rhs.to_std();
479struct is_generator_value
480 : std::is_base_of<gen_value_base<std::decay_t<T>>, std::decay_t<T>> {};
485
486
492 template <
typename T>
print(
const T &val,
char sep =
' ') {
493 std::ostringstream oss;
494 write(oss, val, sep);
497 template <
typename T>
498 print(
const std::initializer_list<T> &il,
char sep =
' ') {
499 std::ostringstream oss;
500 write(oss, std::vector<T>(il), sep);
503 template <
typename T>
504 print(
const std::initializer_list<std::initializer_list<T>> &il,
506 std::ostringstream oss;
507 std::vector<std::vector<T>> mat;
508 for (
const auto &i : il)
510 write(oss, mat, sep);
514 template <
typename T>
void write(std::ostream &os,
const T &val,
char sep) {
515 if constexpr (detail::is_pair<T>::value) {
516 if constexpr (detail::is_pair_multiline<T>::value) {
517 write(os, val.first, sep);
519 write(os, val.second, sep);
522 write(os, val.first,
' ');
524 write(os, val.second,
' ');
526 }
else if constexpr (detail::is_tuple<T>::value)
527 write_tuple(os, val, sep);
528 else if constexpr (detail::is_container<T>::value)
529 write_container(os, val, sep);
530 else if constexpr (std::is_same_v<T, detail::i128>
or
531 std::is_same_v<T, detail::u128>)
532 write_128_number(os, val);
538 template <
typename T>
void write_128_number(std::ostream &os, T num) {
539 static const long long BASE = 1e18;
547 write_128_number(os, num / BASE);
548 os << std::setw(18) << std::setfill(
'0')
549 <<
static_cast<
long long>(num % BASE);
551 os <<
static_cast<
long long>(num);
554 template <
typename C>
555 void write_container(std::ostream &os,
const C &container,
char sep) {
558 for (
const auto &e : container) {
560 os << (detail::is_container_multiline<C>::value ?
'\n' : sep);
562 write(os, e, detail::is_container_multiline<C>::value ? sep :
' ');
567 template <
typename Tuple, size_t... I>
568 void write_tuple_impl(std::ostream &os,
const Tuple &tp,
char sep,
569 std::index_sequence<I...>) {
571 ((os << (first ? (first =
false,
"")
572 : (detail::is_tuple_multiline<Tuple>::value
574 : std::string(1, sep))),
575 write(os, std::get<I>(tp),
576 detail::is_tuple_multiline<Tuple>::value ? sep :
' ')),
579 template <
typename T>
580 void write_tuple(std::ostream &os,
const T &tp,
char sep) {
581 write_tuple_impl(os, tp, sep,
582 std::make_index_sequence<std::tuple_size<T>::value>{});
585 friend std::ostream &operator<<(std::ostream &out,
const print &pr) {
592 template <
typename T>
594 template <
typename T>
595 println(
const std::initializer_list<T> &il,
char sep =
' ')
597 template <
typename T>
598 println(
const std::initializer_list<std::initializer_list<T>> &il,
602 friend std::ostream &operator<<(std::ostream &out,
const println &pr) {
603 return out << pr.s_ <<
'\n';
621 ((detail::is_container<std::decay_t<Args>>::value
or
622 detail::is_sequential<std::decay_t<Args>>::value)
and
624 "print_cols: arguments must be containers or sequential generator "
626 std::ostringstream oss;
631 void write(std::ostream &os,
const Args &...args) {
632 auto views = std::apply(
633 [](
const Args &...inner_args) {
634 return std::make_tuple(
635 detail::print_cols_view<
decltype(inner_args)>{
638 std::forward_as_tuple(args...));
640 const std::size_t n = std::get<0>(views).size();
642 auto check = [&](
const auto &v) {
643 tgen_ensure(v.size() == n,
"print_cols: sizes should be the same");
645 std::apply([&](
const auto &...v) { (check(v), ...); }, views);
647 for (std::size_t i = 0; i < n; ++i) {
651 [&](
const auto &...v) {
652 ((os << (first ?
"" :
" ") <<
print(v.get(i)),
660 std::apply([](
auto &...v) { (v.advance(), ...); }, views);
664 friend std::ostream &operator<<(std::ostream &out,
const print_cols &pr) {
670
671
681using uniform_int_t = std::conditional_t<
682 (
sizeof(T) >=
sizeof(
short)), T,
683 std::conditional_t<std::is_signed_v<T>,
int,
unsigned int>>;
689template <
typename T> T
next(T right) {
690 detail::ensure_registered();
691 if constexpr (std::is_integral_v<T>) {
692 tgen_ensure(right >= 1,
"value for `next` must be valid");
693 return static_cast<T>(
694 std::uniform_int_distribution<detail::uniform_int_t<T>>(
696 static_cast<detail::uniform_int_t<T>>(right) - 1)(detail::rng));
697 }
else if constexpr (std::is_floating_point_v<T>) {
698 tgen_ensure(right >= 0,
"value for `next` must be valid");
699 return std::uniform_real_distribution<T>(0, right)(detail::rng);
701 throw detail::error(
"invalid type for next (" +
702 std::string(
typeid(T).name()) +
")");
710template <
typename T> T
next(T left, T right) {
711 detail::ensure_registered();
712 tgen_ensure(left <= right,
"range for `next` must be valid");
713 if constexpr (std::is_integral_v<T>)
714 return static_cast<T>(
715 std::uniform_int_distribution<detail::uniform_int_t<T>>(
716 static_cast<detail::uniform_int_t<T>>(left),
717 static_cast<detail::uniform_int_t<T>>(right))(detail::rng));
718 else if constexpr (std::is_floating_point_v<T>)
719 return std::uniform_real_distribution<T>(left, right)(detail::rng);
721 throw detail::error(
"invalid type for next (" +
722 std::string(
typeid(T).name()) +
")");
747template <
typename T> T
wnext(T right,
int w) {
750 T val = next<T>(right);
751 for (
int i = 0; i < w; ++i)
752 val = std::max(val, next<T>(right));
753 for (
int i = 0; i < -w; ++i)
754 val = std::min(val, next<T>(right));
759 double x, r = next<
double>(0, 1);
762 x = std::pow(r, 1.0 / (w + 1));
764 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
772template <
typename T> T
wnext(T left, T right,
int w) {
775 T val = next<T>(left, right);
776 for (
int i = 0; i < w; ++i)
777 val = std::max(val, next<T>(left, right));
778 for (
int i = 0; i < -w; ++i)
779 val = std::min(val, next<T>(left, right));
784 double x, r = next<
double>(0, 1);
787 x = std::pow(r, 1.0 / (w + 1));
789 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
792 return left + T(x * (right - left));
799inline u128 next128(u128 total) {
800 tgen_ensure(total > 0,
"next128: total must be positive");
803 u128 limit = (u128(-1) / total) * total;
807 u128 r = (u128(next<uint64_t>(0, std::numeric_limits<uint64_t>::max()))
809 next<uint64_t>(0, std::numeric_limits<uint64_t>::max());
827 static_assert(std::is_arithmetic_v<T>,
828 "weighted_sampler requires an arithmetic weight type");
836 std::vector<storage_t> weight_;
837 std::vector<
int> alias_;
844 : n_(
static_cast<
int>(distribution.size())),
alias_(
n_) {
846 "weighted_sampler: distribution must be non-empty");
847 for (
const auto &w : distribution)
849 "weighted_sampler: distribution must be non-negative");
851 total_ = std::accumulate(distribution.begin(), distribution.end(),
854 std::queue<
int> big, small;
855 for (
int i = 0; i < n_; ++i) {
856 weight_.push_back(storage_t(n_) * storage_t(distribution[i]));
857 if (weight_[i] < total_)
863 while (!small.empty()
and !big.empty()) {
864 int s = small.front();
871 weight_[b] -= total_ - weight_[s];
872 if (weight_[b] < total_)
878 detail::tgen_ensure_against_bug(
879 small.empty(),
"weighted_sampler: small must be empty");
883 while (!big.empty()) {
886 if constexpr (std::is_integral_v<T>) {
887 detail::tgen_ensure_against_bug(
888 weight_[b] == total_,
889 "weighted_sampler: weight of big element must be total");
894 weighted_sampler(
const std::initializer_list<T> &distribution)
895 : weighted_sampler(std::vector<T>(distribution)) {}
899 static detail::u128 sample_below(detail::u128 total) {
900 return detail::next128(total);
902 static double sample_below(
double total) {
903 return tgen::next<
double>(0, total);
910 int i = tgen::next<
int>(0, n_ - 1);
911 return sample_below(total_) < weight_[i] ? i : alias_[i];
926size_t next_by_distribution(
const std::initializer_list<T> &distribution) {
927 return next_by_distribution(std::vector<T>(distribution));
935 const std::vector<T> &distribution) {
936 tgen_ensure(distribution.size() > 0,
"distribution must be non-empty");
937 tgen_ensure(k >= 0,
"number of elements to choose must be non-negative");
940 std::vector<
int> res;
941 for (
int i = 0; i < k; ++i)
942 res.push_back(
static_cast<
int>(am.next()));
947many_by_distribution(
int k,
const std::initializer_list<T> &distribution) {
948 return many_by_distribution(k, std::vector<T>(distribution));
953template <
typename It>
void shuffle(It first, It last) {
957 for (It i = first + 1; i != last; ++i)
958 std::iter_swap(i, first + next(0,
static_cast<
int>(i - first)));
963template <
typename C> [[nodiscard]]
auto shuffled(
const C &container) {
964 if constexpr (detail::is_associative_container<C>::value) {
965 std::vector<
typename C::value_type> vec(container.begin(),
967 shuffle(vec.begin(), vec.end());
970 auto new_container = container;
971 shuffle(new_container.begin(), new_container.end());
972 return new_container;
976[[nodiscard]] std::vector<T> shuffled(
const std::initializer_list<T> &il) {
977 return shuffled(std::vector<T>(il));
983 int size =
static_cast<
int>(std::distance(first, last));
984 tgen_ensure(size > 0,
"cannot pick from empty range");
986 std::advance(it, next(0, size - 1));
993 return pick(container.begin(), container.end());
995template <
typename T> T pick(
const std::initializer_list<T> &il) {
996 return pick(std::vector<T>(il));
1001template <
typename C,
typename T>
1003 std::vector<T> distribution) {
1004 tgen_ensure(container.size() == distribution.size(),
1005 "container and distribution must have the same size");
1006 auto it = container.begin();
1007 std::advance(it, next_by_distribution(distribution));
1010template <
typename C,
typename T>
1011typename C::value_type
1012pick_by_distribution(
const C &container,
1013 const std::initializer_list<T> &distribution) {
1014 return pick_by_distribution(container, std::vector<T>(distribution));
1016template <
typename T,
typename U>
1017T pick_by_distribution(
const std::initializer_list<T> &il,
1018 const std::vector<U> &distribution) {
1019 return pick_by_distribution(std::vector<T>(il), distribution);
1021template <
typename T,
typename U>
1022T pick_by_distribution(
const std::initializer_list<T> &il,
1023 const std::initializer_list<U> &distribution) {
1024 return pick_by_distribution(std::vector<T>(il),
1025 std::vector<U>(distribution));
1030template <
typename C> C
choose(
const C &container,
int k) {
1031 tgen_ensure(0 < k
and k <=
static_cast<
int>(container.size()),
1032 "number of elements to choose must be valid");
1033 std::vector<
typename C::value_type> new_vec;
1035 int need = k, left =
static_cast<
int>(container.size());
1036 for (
auto cur_it = container.begin(); cur_it != container.end(); ++cur_it) {
1037 if (next(1, left--) <= need) {
1038 new_container.insert(new_container.end(), *cur_it);
1042 return new_container;
1044template <
typename T>
1045std::vector<T> choose(
const std::initializer_list<T> &il,
int k) {
1046 return choose(std::vector<T>(il), k);
1055 std::unordered_map<T, T> virtual_list_;
1058 static constexpr size_t array_pool_max =
size_t{1} << 23;
1062 : left_(left), right_(right),
1063 num_available_(
static_cast<T>(right - left + 1)) {}
1066 T
size()
const {
return num_available_; }
1075 T i = next<T>(0,
size() - 1);
1078 auto vi_it = virtual_list_.find(i);
1079 T vi = vi_it == virtual_list_.end() ? i : vi_it->second;
1080 auto vj_it = virtual_list_.find(j);
1081 T vj = vj_it == virtual_list_.end() ? j : vj_it->second;
1082 virtual_list_[i] = vj;
1093 tgen_ensure(count >= 0,
"distinct_range: size must be nonnegative");
1095 "distinct_range: no more values to generate");
1097 size_t range_size =
static_cast<size_t>(right_ - left_ + 1);
1098 size_t sample_count =
static_cast<size_t>(count);
1101 if (sample_count > 0) {
1102 if (range_size <= array_pool_max)
1103 res = sample_from_pool(sample_count, range_size);
1104 else if (sample_count * 2 > range_size)
1105 res = sample_complement(sample_count, range_size);
1107 res = sample_sparse(sample_count);
1110 num_available_ -=
static_cast<T>(count);
1111 virtual_list_.clear();
1112 return typename list<T>::value(res);
1122 std::vector<T> sample_from_pool(size_t count, size_t range_size) {
1123 std::vector<T> pool(range_size);
1124 std::iota(pool.begin(), pool.end(), left_);
1125 for (size_t i = 0; i < count; ++i) {
1126 size_t j = next<size_t>(i, range_size - 1);
1127 std::swap(pool[i], pool[j]);
1135 std::vector<T> sample_complement(size_t count, size_t range_size) {
1136 size_t exclude_count = range_size - count;
1137 std::unordered_set<T> excluded;
1138 excluded.reserve(exclude_count * 2);
1140 if (exclude_count <= array_pool_max) {
1141 for (T value : sample_from_pool(exclude_count, range_size))
1142 excluded.insert(value);
1144 for (T value : sample_sparse(exclude_count))
1145 excluded.insert(value);
1150 for (T value = left_; value <= right_; ++value) {
1151 if (!excluded.count(value))
1152 res.push_back(value);
1154 detail::tgen_ensure_against_bug(
1155 res.size() == count,
"distinct_range: complement sampling failed");
1161 std::vector<T> sample_sparse(size_t count) {
1162 std::unordered_map<T, T> local_virtual;
1163 local_virtual.reserve(count * 2);
1164 T remaining = range_span();
1167 for (size_t step = 0; step < count; ++step) {
1168 T i = next<T>(0, remaining - 1);
1169 T j = remaining - 1;
1171 auto vi_it = local_virtual.find(i);
1172 T vi = vi_it == local_virtual.end() ? i : vi_it->second;
1173 auto vj_it = local_virtual.find(j);
1174 T vj = vj_it == local_virtual.end() ? j : vj_it->second;
1175 local_virtual[i] = vj;
1177 res.push_back(vi + left_);
1185 T range_span() {
return static_cast<T>(right_ - left_ + 1); }
1190 std::vector<T> list_;
1191 distinct_range<size_t> idx_;
1194 template <
typename C>
1198 distinct_container(
const std::initializer_list<T> &il)
1199 : distinct_container(std::vector<T>(il)) {}
1206 T
gen() {
return list_[idx_.gen()]; }
1212 for (
int i = 0; i < size; ++i)
1213 res.push_back(
gen());
1214 return typename list<T>::value(res);
1222 res.push_back(
gen());
1223 return typename list<T>::value(res);
1226template <
typename C>
1230
1231
1232
1233
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1251
1252
1256 detail::cpp = detail::cpp_value(version);
1260
1261
1265 return {compiler_kind::gcc, major, minor};
1270 return {compiler_kind::clang, major, minor};
1275 detail::compiler.kind_ = compiler.kind_;
1276 detail::compiler.major_ = compiler.major_;
1277 detail::compiler.minor_ = compiler.minor_;
1284inline bool process_special_opt_flags(std::string &key) {
1286 if (key.find(
"tgen::CPP:") == 0) {
1287 size_t prefix_len = std::string(
"tgen::CPP:").size();
1289 std::isdigit(key[prefix_len])
and
1290 std::isdigit(key[prefix_len + 1]),
1291 "invalid CPP format");
1292 int version = std::stoi(key.substr(prefix_len, 2));
1300 size_t prefix_len = 0;
1302 if (key.find(
"tgen::GCC") == 0) {
1303 kind = compiler_kind::gcc;
1304 prefix_len = std::string(
"tgen::GCC").size();
1305 }
else if (key.find(
"tgen::CLANG") == 0) {
1306 kind = compiler_kind::clang;
1307 prefix_len = std::string(
"tgen::CLANG").size();
1312 if (key.size() == prefix_len) {
1317 tgen_ensure(key[prefix_len] ==
':',
"invalid compiler format");
1320 std::string inside = key.substr(prefix_len, key.size() - prefix_len);
1321 int major = 0, minor = 0;
1323 size_t dot = inside.find(
'.');
1324 if (dot == std::string::npos) {
1326 std::all_of(inside.begin(), inside.end(), ::isdigit),
1327 "invalid compiler version");
1328 major = std::stoi(inside);
1330 std::string maj = inside.substr(0, dot);
1331 std::string min = inside.substr(dot + 1);
1334 std::all_of(maj.begin(), maj.end(), ::isdigit)
and
1336 "invalid compiler major version");
1338 std::all_of(min.begin(), min.end(), ::isdigit)
and
1340 "invalid compiler minor version");
1342 major = std::stoi(maj);
1343 minor = std::stoi(min);
1351inline std::vector<std::string>
1353inline std::map<std::string, std::string>
1356template <
typename T> T get_opt(
const std::string &value) {
1358 if constexpr (std::is_same_v<T,
bool>) {
1359 if (value ==
"true" or value ==
"1")
1361 if (value ==
"false" or value ==
"0")
1363 }
else if constexpr (std::is_integral_v<T>) {
1364 if constexpr (std::is_unsigned_v<T>)
1365 return static_cast<T>(std::stoull(value));
1367 return static_cast<T>(std::stoll(value));
1368 }
else if constexpr (std::is_floating_point_v<T>)
1369 return static_cast<T>(std::stold(value));
1375 throw error(
"invalid value `" + value +
"` for type " +
typeid(T).name());
1378inline void parse_opts(
int argc,
char **argv) {
1381 for (
int i = 1; i < argc; ++i) {
1382 std::string key(argv[i]);
1384 if (process_special_opt_flags(key))
1387 if (key[0] ==
'-') {
1389 "invalid opt (" + std::string(argv[i]) +
")");
1390 if (
'0' <= key[1]
and key[1] <=
'9') {
1392 pos_opts.push_back(key);
1397 key = key.substr(1);
1400 pos_opts.push_back(key);
1405 if (key[0] ==
'-') {
1407 "invalid opt (" + std::string(argv[i]) +
")");
1410 key = key.substr(1);
1417 std::size_t eq = key.find(
'=');
1418 if (eq != std::string::npos) {
1420 std::string value = key.substr(eq + 1);
1421 key = key.substr(0, eq);
1423 "expected non-empty key/value in opt (" +
1424 std::string(argv[i]) +
")");
1426 "cannot have repeated keys");
1427 named_opts[key] = value;
1431 "cannot have repeated keys");
1432 tgen_ensure(argv[i + 1],
"value cannot be empty");
1433 named_opts[key] = std::string(argv[i + 1]);
1439inline void set_seed(
int argc,
char **argv) {
1440 std::vector<uint32_t> seed;
1443 for (
int i = 1; i < argc; ++i) {
1445 size_t size_pos = seed.size();
1447 for (
char *s = argv[i]; *s !=
'\0'; ++s) {
1452 std::seed_seq seq(seed.begin(), seed.end());
1460 detail::ensure_registered();
1461 return index < detail::pos_opts.size();
1466 detail::ensure_registered();
1467 return detail::named_opts.count(key) != 0;
1469template <
typename K>
1470std::enable_if_t<std::is_same_v<K,
char>,
bool> has_opt(K key) {
1476template <
typename T>
1477T
opt(size_t index, std::optional<T> default_value = std::nullopt) {
1478 detail::ensure_registered();
1479 if (!has_opt(index)) {
1481 return *default_value;
1482 throw detail::error(
"cannot find opt at index " +
1483 std::to_string(index));
1485 return detail::get_opt<T>(detail::pos_opts[index]);
1490template <
typename T>
1491T
opt(
const std::string &key, std::optional<T> default_value = std::nullopt) {
1492 detail::ensure_registered();
1495 return *default_value;
1496 throw detail::error(
"cannot find opt with key " + key);
1498 return detail::get_opt<T>(detail::named_opts[key]);
1500template <
typename T,
typename K>
1501std::enable_if_t<std::is_same_v<K,
char>, T>
1502opt(K key, std::optional<T> default_value = std::nullopt) {
1503 return opt<T>(std::string(1, key), default_value);
1508 detail::set_seed(argc, argv);
1510 detail::pos_opts.clear();
1511 detail::named_opts.clear();
1512 detail::parse_opts(argc, argv);
1514 detail::registered =
true;
1520 detail::rng.seed(*seed);
1524 detail::pos_opts.clear();
1525 detail::named_opts.clear();
1527 detail::registered =
true;
1531
1532
1533
1534
1537
1538
1539
1540
1544 T value_l_, value_r_;
1545 std::set<T> values_;
1550 mutable std::vector<std::pair<T, T>>
1552 mutable std::vector<std::vector<
int>> neigh_;
1553 std::vector<std::set<
int>>
1555 bool index_constraints_{
1557 mutable bool uses_full_range_{
1562 list(
int size, T value_left, T value_right)
1563 : size_(size), value_l_(value_left), value_r_(value_right),
1564 uses_full_range_(
true) {
1565 tgen_ensure(size_ > 0,
"list: size must be positive");
1566 tgen_ensure(value_l_ <= value_r_,
"list: value range must be valid");
1572 tgen_ensure(size_ > 0,
"list: size must be positive");
1573 tgen_ensure(!values.empty(),
"list: value set must be non-empty");
1574 value_l_ = 0, value_r_ =
static_cast<T>(values.size() - 1);
1575 val_range_.assign(size_, {value_l_, value_r_});
1577 for (T val : values_)
1578 value_idx_in_set_[val] = idx++;
1583 tgen_ensure(0 <= idx
and idx < size_,
"list: index must be valid");
1584 ensure_val_range_materialized();
1585 if (values_.size() == 0) {
1586 auto &[left, right] = val_range_[idx];
1587 if (left == right
and value_l_ != value_r_) {
1589 "list: must not set to two different values");
1592 "list: value must be in the defined range");
1597 "list: value must be in the set of values");
1598 auto &[left, right] = val_range_[idx];
1599 T new_val =
static_cast<T>(value_idx_in_set_[val]);
1601 "list: must not set to two different values");
1602 left = right = new_val;
1604 index_constraints_ =
true;
1611 std::max(idx_1, idx_2) < size_,
1612 "list: indices must be valid");
1616 ensure_val_range_materialized();
1617 ensure_neigh_allocated();
1618 index_constraints_ =
true;
1619 neigh_[idx_1].push_back(idx_2);
1620 neigh_[idx_2].push_back(idx_1);
1626 if (!indices.empty()) {
1627 std::set<
int>::iterator beg = indices.begin();
1628 for (
auto it = std::next(beg); it != indices.end(); ++it)
1636 tgen_ensure(0 <= left
and left <= right
and right < size_,
1637 "list: range indices must be valid");
1638 for (
int i = left; i < right; ++i)
1650 if (!indices.empty())
1651 diff_restrictions_.push_back(indices);
1657 std::set<
int> indices = {idx_1, idx_2};
1663 tgen_ensure(0 <= left
and left <= right
and right < size_,
1664 "list: range indices must be valid");
1665 std::vector<
int> indices(right - left + 1);
1666 std::iota(indices.begin(), indices.end(), left);
1667 return different(std::set<
int>(indices.begin(), indices.end()));
1672 std::vector<
int> indices(size_);
1673 std::iota(indices.begin(), indices.end(), 0);
1674 return different(std::set<
int>(indices.begin(), indices.end()));
1679 for (
int i = 1; i < size_; ++i)
1687 using tgen_is_sequential_tag = detail::is_sequential_tag;
1689 using value_type = T;
1692 std::vector<T> vec_;
1696 value(
const std::initializer_list<T> &il) : value(std::vector<T>(il)) {}
1699 int size()
const {
return static_cast<
int>(vec_.size()); }
1704 "list: value: index out of bounds");
1707 const T &operator[](
int idx)
const {
1709 "list: value: index out of bounds");
1716 std::sort(vec_.begin(), vec_.end());
1723 std::reverse(vec_.begin(), vec_.end());
1737 std::vector<T> new_vec = vec_;
1738 for (
int i = 0; i < rhs
.size(); ++i)
1739 new_vec.push_back(rhs[i]);
1740 return value(new_vec);
1746 for (
int i = 0; i < size(); ++i)
1747 std::swap(vec_[i], vec_[next(0, size() - 1)]);
1753 T
pick()
const {
return vec_[next<
int>(0, size() - 1)]; }
1757 template <
typename Dist>
1760 "value and distribution must have the same size");
1761 return vec_[next_by_distribution(distribution)];
1763 template <
typename Dist>
1764 T pick_by_distribution(
1765 const std::initializer_list<Dist> &distribution)
const {
1766 return pick_by_distribution(std::vector<Dist>(distribution));
1773 "number of elements to choose must be valid");
1774 std::vector<T> new_vec;
1776 for (
int i = 0; need > 0; ++i) {
1778 if (next(1, left) <= need) {
1779 new_vec.push_back(vec_[i]);
1783 return value(new_vec);
1787 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
1788 for (
int i = 0; i < val.size(); ++i) {
1798 if constexpr (!detail::is_generator_value<T>::value) {
1801 std::vector<
typename T::std_type> vec;
1802 for (
const auto &i : vec_)
1803 vec.push_back(i.to_std());
1813 if (diff_restrictions_.empty()) {
1814 if (
auto unconstrained = try_gen_unconstrained())
1815 return *unconstrained;
1817 if (
auto all_different = try_gen_all_different())
1818 return *all_different;
1820 ensure_neigh_allocated();
1821 std::vector<T> vec(size_);
1822 std::vector<
bool> defined_idx(
1825 std::vector<
int> comp_id(size_, -1);
1826 std::vector<std::vector<
int>> comp(size_);
1830 auto define_comp = [&](
int cur_comp, T val) {
1831 for (
int idx : comp[cur_comp]) {
1834 defined_idx[idx] =
true;
1840 std::vector<
bool> vis(size_,
false);
1841 for (
int idx = 0; idx < size_; ++idx)
1844 bool value_defined =
false;
1848 std::queue<
int> q({idx});
1850 std::vector<
int> component;
1851 while (!q.empty()) {
1852 int cur_idx = q.front();
1855 component.push_back(cur_idx);
1858 auto [l, r] = val_range_at(cur_idx);
1860 if (!value_defined) {
1862 value_defined =
true;
1864 }
else if (new_value != l) {
1866 throw detail::contradiction_error(
1868 "tried to set value to `" +
1869 std::to_string(new_value) +
1870 "`, but it was already set as `" +
1871 std::to_string(l) +
"`");
1875 for (
int nxt_idx : neigh_[cur_idx]) {
1876 if (!vis[nxt_idx]) {
1877 vis[nxt_idx] =
true;
1884 for (
int cur_idx : component) {
1885 comp_id[cur_idx] = comp_count;
1886 comp[comp_id[cur_idx]].push_back(cur_idx);
1891 define_comp(comp_count, new_value);
1898 std::vector<std::set<
int>> diff_containing_comp_idx(comp_count);
1901 for (
const std::set<
int> &diff : diff_restrictions_) {
1903 if (
static_cast<uint64_t>(diff.size() - 1) +
1904 static_cast<uint64_t>(value_l_) >
1905 static_cast<uint64_t>(value_r_))
1906 throw detail::contradiction_error(
1907 "list",
"tried to generate " +
1908 std::to_string(diff.size()) +
1909 " different values, but the maximum is " +
1910 std::to_string(value_r_ - value_l_ + 1));
1914 std::set<
int> comp_ids;
1915 for (
int idx : diff) {
1916 if (comp_ids.count(comp_id[idx]))
1917 throw detail::contradiction_error(
1918 "list",
"tried to set two indices as equal and "
1920 comp_ids.insert(comp_id[idx]);
1922 diff_containing_comp_idx[comp_id[idx]].insert(dist_id);
1929 for (
auto &diff_containing : diff_containing_comp_idx)
1930 if (diff_containing.size() >= 3)
1931 throw detail::complex_restrictions_error(
1933 "one index cannot be in >= 3 'different' restrictions");
1935 std::vector<
bool> vis_diff(diff_restrictions_.size(),
false);
1936 std::vector<
bool> initially_defined_comp_idx(comp_count,
false);
1939 auto define_tree = [&](
int diff_id) {
1944 std::set<T> defined_values;
1945 for (
int idx : diff_restrictions_[diff_id])
1946 if (defined_idx[idx]) {
1949 if (defined_values.count(vec[idx]))
1950 throw detail::contradiction_error(
1952 "tried to set two indices as equal and different");
1954 defined_values.insert(vec[idx]);
1959 int new_value_count =
1960 static_cast<
int>(diff_restrictions_[diff_id].size()) -
1961 static_cast<
int>(defined_values.size());
1962 std::vector<T> generated_values =
1963 generate_distinct_values(new_value_count, defined_values);
1964 auto val_it = generated_values.begin();
1965 for (
int idx : diff_restrictions_[diff_id])
1966 if (defined_idx[idx]) {
1969 initially_defined_comp_idx[comp_id[idx]] =
false;
1971 define_comp(comp_id[idx], *val_it);
1977 std::queue<std::pair<
int,
int>> q;
1978 q.emplace(diff_id, -1);
1979 vis_diff[diff_id] =
true;
1980 while (!q.empty()) {
1981 auto [cur_diff, parent] = q.front();
1984 std::set<
int> neigh_diff;
1985 for (
int idx : diff_restrictions_[cur_diff])
1987 diff_containing_comp_idx[comp_id[idx]]) {
1988 if (nxt_diff == cur_diff
or nxt_diff == parent)
1992 if (vis_diff[nxt_diff])
1993 throw detail::complex_restrictions_error(
1995 "cycle found in 'different' restrictions");
1997 neigh_diff.insert(nxt_diff);
2000 for (
int nxt_diff : neigh_diff) {
2001 vis_diff[nxt_diff] =
true;
2002 q.emplace(nxt_diff, cur_diff);
2005 std::set<T> nxt_defined_values;
2006 for (
int idx2 : diff_restrictions_[nxt_diff])
2007 if (defined_idx[idx2]) {
2011 if (initially_defined_comp_idx[comp_id[idx2]])
2012 throw detail::complex_restrictions_error(
2015 nxt_defined_values.insert(vec[idx2]);
2017 int new_value_count =
2018 static_cast<
int>(diff_restrictions_[nxt_diff].size()) -
2019 static_cast<
int>(nxt_defined_values.size());
2020 std::vector<T> generated_values = generate_distinct_values(
2021 new_value_count, nxt_defined_values);
2022 auto val_it = generated_values.begin();
2023 for (
int idx2 : diff_restrictions_[nxt_diff])
2024 if (!defined_idx[idx2]) {
2025 define_comp(comp_id[idx2], *val_it);
2037 std::vector<std::pair<
int,
int>> defined_cnt_and_diff_idx;
2039 for (
const std::set<
int> &diff : diff_restrictions_) {
2040 int defined_cnt = 0;
2041 for (
int idx : diff)
2042 if (defined_idx[idx]) {
2044 initially_defined_comp_idx[comp_id[idx]] =
true;
2046 defined_cnt_and_diff_idx.emplace_back(defined_cnt, dist_id);
2050 std::sort(defined_cnt_and_diff_idx.rbegin(),
2051 defined_cnt_and_diff_idx.rend());
2052 for (
auto [defined_cnt, diff_idx] : defined_cnt_and_diff_idx)
2053 if (!vis_diff[diff_idx])
2054 define_tree(diff_idx);
2058 for (std::size_t dist_id = 0; dist_id < diff_restrictions_.size();
2060 if (!vis_diff[dist_id])
2061 define_tree(
static_cast<
int>(dist_id));
2067 for (
int idx = 0; idx < size_; ++idx)
2068 if (!defined_idx[idx])
2069 define_comp(comp_id[idx], next<T>(value_l_, value_r_));
2071 if (!values_.empty()) {
2073 std::vector<T> value_vec(values_.begin(), values_.end());
2075 val = value_vec[val];
2083 void ensure_neigh_allocated()
const {
2084 if (neigh_.size() ==
static_cast<size_t>(size_))
2086 neigh_.assign(size_, {});
2090 void ensure_val_range_materialized()
const {
2091 if (!uses_full_range_)
2093 val_range_.assign(size_, {value_l_, value_r_});
2094 uses_full_range_ =
false;
2098 std::pair<T, T> val_range_at(
int idx)
const {
2099 if (uses_full_range_)
2100 return {value_l_, value_r_};
2101 return val_range_[idx];
2107 generate_distinct_values(
int k,
const std::set<T> &forbidden_values)
const {
2108 for (
auto forbidden : forbidden_values)
2109 tgen_ensure(value_l_ <= forbidden
and forbidden <= value_r_);
2110 const T num_available =
2111 static_cast<T>((value_r_ - value_l_ + 1) -
2112 static_cast<T>(forbidden_values.size()));
2113 if (num_available < k)
2114 throw detail::complex_restrictions_error(
2115 "list",
"not enough distinct values");
2116 if (forbidden_values.empty())
2117 return distinct_range<T>(value_l_, value_r_).gen_list(k).to_std();
2119 std::map<T, T> virtual_list;
2120 std::vector<T> gen_list;
2121 for (
int i = 0; i < k; ++i) {
2122 T ti =
static_cast<T>(i);
2123 T j = next<T>(ti, num_available - 1);
2124 T vj = virtual_list.count(j) ? virtual_list[j] : j;
2125 T vi = virtual_list.count(ti) ? virtual_list[ti] : ti;
2127 virtual_list[j] = vi, virtual_list[ti] = vj;
2129 gen_list.push_back(virtual_list[ti]);
2132 for (T &val : gen_list)
2135 std::vector<std::pair<T,
int>> values_sorted;
2136 for (std::size_t i = 0; i < gen_list.size(); ++i)
2137 values_sorted.emplace_back(gen_list[i], i);
2138 std::sort(values_sorted.begin(), values_sorted.end());
2139 auto cur_it = forbidden_values.begin();
2140 int smaller_forbidden_count = 0;
2141 for (
auto [val, idx] : values_sorted) {
2142 while (cur_it != forbidden_values.end()
and
2143 *cur_it <= val + smaller_forbidden_count)
2144 ++cur_it, ++smaller_forbidden_count;
2145 gen_list[idx] +=
static_cast<T>(smaller_forbidden_count);
2154 std::optional<
value> try_gen_unconstrained()
const {
2155 if (!values_.empty()
or index_constraints_)
2156 return std::nullopt;
2158 std::vector<T> vec(size_);
2159 for (
int i = 0; i < size_; ++i)
2160 vec[i] = next<T>(value_l_, value_r_);
2168 std::optional<
value> try_gen_all_different()
const {
2169 if (!values_.empty()
or diff_restrictions_.size() != 1)
2170 return std::nullopt;
2172 const std::set<
int> &diff = diff_restrictions_[0];
2173 if (
static_cast<
int>(diff.size()) != size_
or *diff.begin() != 0
or
2174 *diff.rbegin() != size_ - 1)
2175 return std::nullopt;
2177 if (!neigh_.empty()) {
2178 for (
const auto &adj : neigh_) {
2180 return std::nullopt;
2184 if (index_constraints_)
2185 return std::nullopt;
2187 if (
static_cast<
long long>(size_) >
2188 static_cast<
long long>(value_r_) - value_l_ + 1)
2189 throw detail::contradiction_error(
2190 "list",
"tried to generate " + std::to_string(size_) +
2191 " different values, but the maximum is " +
2192 std::to_string(value_r_ - value_l_ + 1));
2199
2200
2201
2202
2205
2206
2207
2208
2212 std::vector<std::pair<
int,
int>> defs_;
2213 std::optional<std::vector<
int>> cycle_sizes_;
2217 tgen_ensure(size_ > 0,
"permutation: size must be positive");
2223 "permutation: index must be valid");
2224 defs_.emplace_back(idx, val);
2231 size_ == std::accumulate(cycle_sizes.begin(), cycle_sizes.end(), 0),
2232 "permutation: cycle sizes must add up to size of permutation");
2233 cycle_sizes_ = cycle_sizes;
2236 permutation &cycles(
const std::initializer_list<
int> &cycle_sizes) {
2237 return cycles(std::vector<
int>(cycle_sizes));
2243 using tgen_is_sequential_tag = detail::is_sequential_tag;
2246 std::vector<
int> vec_;
2248 bool print_1_based_;
2251 :
vec_(
vec), sep_(
' '), print_1_based_(
false) {
2252 tgen_ensure(!vec_.empty(),
"permutation: value: cannot be empty");
2253 std::vector<
bool> vis(vec_.size(),
false);
2254 for (
int i = 0; i <
size(); ++i) {
2256 vec_[i] <
static_cast<
int>(vec_.size()),
2257 "permutation: value: values must be from `0` to "
2260 "permutation: value: cannot have repeated values");
2261 vis[vec_[i]] =
true;
2264 value(
const std::initializer_list<
int> &il)
2265 : value(std::vector<
int>(il)) {}
2268 int size()
const {
return static_cast<
int>(vec_.size()); }
2273 "permutation: value: index out of bounds");
2280 std::vector<
bool> vis(
size(),
false);
2283 for (
int i = 0; i <
size(); ++i)
2286 for (
int j = i; !vis[j]; j = vec_[j])
2290 return ((
size() - cycles) % 2 == 0) ? +1 : -1;
2296 for (
int i = 0; i < size(); ++i)
2304 std::reverse(vec_.begin(), vec_.end());
2311 std::vector<
int> inv(
size());
2312 for (
int i = 0; i < size(); ++i)
2329 print_1_based_ =
true;
2336 for (
int i = 0; i < size(); ++i)
2337 std::swap(vec_[i], vec_[next(0, size() - 1)]);
2343 int pick()
const {
return vec_[next<
int>(0, size() - 1)]; }
2347 template <
typename Dist>
2350 "value and distribution must have the same size");
2351 return vec_[next_by_distribution(distribution)];
2353 template <
typename Dist>
2354 int pick_by_distribution(
2355 const std::initializer_list<Dist> &distribution)
const {
2356 return pick_by_distribution(std::vector<Dist>(distribution));
2360 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
2361 for (
int i = 0; i < val
.size(); ++i) {
2364 out << val
[i
] + val.print_1_based_;
2376 std::vector<
int> out = vec_;
2386 if (!cycle_sizes_) {
2388 std::vector<
int> idx_to_val(size_, -1), val_to_idx(size_, -1);
2389 for (
auto [idx, val] : defs_) {
2391 0 <= val
and val < size_,
2392 "permutation: value in permutation must be in [0, " +
2393 std::to_string(size_) +
")");
2395 if (idx_to_val[idx] != -1) {
2397 "permutation: cannot set an index to two "
2398 "different values");
2400 idx_to_val[idx] = val;
2402 if (val_to_idx[val] != -1) {
2404 "permutation: cannot set two indices to the "
2407 val_to_idx[val] = idx;
2410 std::vector<
int> perm(size_);
2411 std::iota(perm.begin(), perm.end(), 0);
2412 shuffle(perm.begin(), perm.end());
2414 for (
int &i : idx_to_val)
2417 while (val_to_idx[perm[cur_idx]] != -1)
2419 i = perm[cur_idx++];
2425 std::vector<
int> order(size_);
2426 std::iota(order.begin(), order.end(), 0);
2427 shuffle(order.begin(), order.end());
2429 std::vector<std::vector<
int>> cycles;
2430 for (
int cycle_size : *cycle_sizes_) {
2431 cycles.emplace_back();
2432 for (
int i = 0; i < cycle_size; ++i)
2433 cycles.back().push_back(order[idx++]);
2437 std::vector<
int> perm(size_, -1);
2438 for (
const std::vector<
int> &cycle : cycles) {
2439 int cur_size =
static_cast<
int>(cycle.size());
2440 for (
int i = 0; i < cur_size; ++i)
2441 perm[cycle[i]] = cycle[(i + 1) % cur_size];
2449
2450
2451
2452
2458using namespace tgen::detail;
2460inline int popcount(uint64_t x) {
return __builtin_popcountll(x); }
2462inline int ctzll(uint64_t x) {
2465 static const unsigned char index64[64] = {
2466 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
2467 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
2468 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
2469 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12};
2470 return index64[((x & -x) * 0x022FDD63CC95386D) >> 58];
2473inline uint64_t mul_mod(uint64_t a, uint64_t b, uint64_t m) {
2474 return static_cast<uint64_t>(
static_cast<u128>(a) * b % m);
2479inline uint64_t expo_mod(uint64_t x, uint64_t y, uint64_t m) {
2482 uint64_t ans = expo_mod(mul_mod(x, x, m), y / 2, m);
2483 return y % 2 ? mul_mod(x, ans, m) : ans;
2492 if (n == 2
or n == 3)
2497 uint64_t r = detail::ctzll(n - 1), d = n >> r;
2499 for (
int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
2500 uint64_t x = detail::expo_mod(a, d, n);
2501 if (x == 1
or x == n - 1
or a % n == 0)
2504 for (uint64_t j = 0; j < r - 1; ++j) {
2505 x = detail::mul_mod(x, x, n);
2517inline uint64_t pollard_rho(uint64_t n) {
2520 auto f = [n](uint64_t x) {
return mul_mod(x, x, n) + 1; };
2522 uint64_t x = 0, y = 0, t = 30, prd = 2, x0 = 1, q;
2523 while (t % 40 != 0
or std::gcd(prd, n) == 1) {
2526 q = mul_mod(prd, x > y ? x - y : y - x, n);
2529 x = f(x), y = f(f(y)), ++t;
2531 return std::gcd(prd, n);
2534inline std::vector<uint64_t> factor(uint64_t n) {
2539 uint64_t d = pollard_rho(n);
2540 std::vector<uint64_t> l = factor(d), r = factor(n / d);
2541 l.insert(l.end(), r.begin(), r.end());
2546template <
typename T>
2547std::runtime_error there_is_no_in_range_error(
const std::string &type, T l,
2549 return error(
"math: there is no " + type +
" in range [" +
2550 std::to_string(l) +
", " + std::to_string(r) +
"]");
2552template <
typename T>
2553std::runtime_error there_is_no_from_error(
const std::string &type, T r) {
2554 return error(
"math: there is no " + type +
" from " + std::to_string(r));
2556template <
typename T>
2557std::runtime_error there_is_no_upto_error(
const std::string &type, T r) {
2558 return error(
"math: there is no " + type +
" up to " + std::to_string(r));
2564inline i128 modular_inverse_128(i128 a, i128 mod) {
2566 "math: modular inverse requires 0 < value < mod");
2568 i128 t = 0, new_t = 1;
2569 i128 r = mod, new_r = a;
2571 while (new_r != 0) {
2574 auto tmp_t = t - q * new_t;
2578 auto tmp_r = r - q * new_r;
2583 tgen_ensure(r == 1,
"math: remainder and mod must be coprime");
2591inline bool mul_leq(uint64_t a, uint64_t b, uint64_t limit) {
2592 if (a == 0
or b == 0)
2594 return a <= limit / b;
2598inline std::optional<uint64_t> expo(uint64_t base, uint64_t exp,
2600 uint64_t result = 1;
2604 if (!mul_leq(result, base, limit))
2605 return std::nullopt;
2614 if (!mul_leq(base, base, limit))
2615 return std::nullopt;
2623inline uint64_t kth_root_floor(uint64_t n, uint64_t k) {
2624 tgen_ensure_against_bug(k > 0,
"math: value must be valid");
2625 if (k == 1
or n <= 1)
2628 uint64_t lo = 1, hi = 1ULL << ((64 + k - 1) / k);
2631 uint64_t mid = lo + (hi - lo + 1) / 2;
2633 if (expo(mid, k, n)) {
2644inline i128 gcd128(i128 a, i128 b) {
2660inline i128 mul_saturate(i128 a, i128 b) {
2662 static const i128 LIMIT =
static_cast<i128>(1) << 64;
2663 if (a == 0
or b == 0)
2674 crt() : a(0), m(1) {}
2675 crt(T a_, T m_) : a(a_), m(m_) {}
2676 crt operator*(crt C) {
2677 if (m == 0
or C.m == 0)
2680 T g = gcd128(m, C.m);
2681 if ((C.a - a) % g != 0)
2690 T inv = modular_inverse_128(m1 % m2, m2);
2692 T k = ((C.a - a) / g) % m2;
2696 k =
static_cast<u128>(k) * inv % m2;
2698 T lcm = mul_saturate(m, m2);
2700 T res = (a +
static_cast<T>((
static_cast<u128>(k) * m) % lcm)) % lcm;
2710inline constexpr long double LOG_ZERO = -INFINITY;
2711inline constexpr long double LOG_ONE = 0.0;
2713inline long double log_space(
long double x) {
2714 return x == 0.0 ? LOG_ZERO : std::log(x);
2718inline long double add_log_space(
long double a,
long double b) {
2723 return a + std::log1p(std::exp(
static_cast<
double>(b - a)));
2728inline long double sub_log_space(
long double a,
long double b) {
2733 return a + std::log1p(-std::exp(
static_cast<
double>(b - a)));
2742 tgen_ensure(n > 0,
"math: number to factor must be positive");
2743 auto factors = detail::factor(n);
2744 std::sort(factors.begin(), factors.end());
2752 tgen_ensure(n > 0,
"math: number to factor must be positive");
2753 std::vector<std::pair<uint64_t,
int>> primes;
2754 for (uint64_t p : factor(n)) {
2755 if (!primes.empty()
and primes.back().first == p)
2756 ++primes.back().second;
2758 primes.emplace_back(p, 1);
2767 return static_cast<uint64_t>(detail::modular_inverse_128(a, mod));
2773 tgen_ensure(n > 0,
"math: totient(0) is undefined");
2776 for (
auto [p, e] : factor_by_prime(n))
2783inline const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> &
2786 static const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> value{
2788 2, 3, 7, 23, 89, 113, 523, 887, 1129, 1327, 9551, 15683, 19609,
2789 31397, 155921, 360653, 370261, 492113, 1349533, 1357201, 2010733,
2790 4652353, 17051707, 20831323, 47326693, 122164747, 189695659,
2791 191912783, 387096133, 436273009, 1294268491, 1453168141,
2792 2300942549, 3842610773, 4302407359, 10726904659, 20678048297,
2793 22367084959, 25056082087, 42652618343, 127976334671, 182226896239,
2794 241160624143, 297501075799, 303371455241, 304599508537,
2795 416608695821, 461690510011, 614487453523, 738832927927,
2796 1346294310749, 1408695493609, 1968188556461, 2614941710599,
2797 7177162611713, 13829048559701, 19581334192423, 42842283925351,
2798 90874329411493, 171231342420521, 218209405436543, 1189459969825483,
2799 1686994940955803, 1693182318746371, 43841547845541059,
2800 55350776431903243, 80873624627234849, 203986478517455989,
2801 218034721194214273, 305405826521087869, 352521223451364323,
2802 401429925999153707, 418032645936712127, 804212830686677669,
2803 1425172824437699411, 5733241593241196731, 6787988999657777797
2805 {1, 2, 4, 6, 8, 14, 18, 20, 22, 34, 36,
2806 44, 52, 72, 86, 96, 112, 114, 118, 132, 148, 154,
2807 180, 210, 220, 222, 234, 248, 250, 282, 288, 292, 320,
2808 336, 354, 382, 384, 394, 456, 464, 468, 474, 486, 490,
2809 500, 514, 516, 532, 534, 540, 582, 588, 602, 652, 674,
2810 716, 766, 778, 804, 806, 906, 916, 924, 1132, 1184, 1198,
2811 1220, 1224, 1248, 1272, 1328, 1356, 1370, 1442, 1476, 1488, 1510}};
2820 throw detail::there_is_no_upto_error(
"prime gap", right);
2822 const auto &[P, G] = prime_gaps();
2823 for (
int i =
static_cast<
int>(P.size()) - 1;; --i) {
2827 uint64_t real_right = std::min(right, P[i] + G[i] - 1);
2828 uint64_t prev = i > 0 ? G[i - 1] : 0;
2829 uint64_t curr = real_right - P[i];
2832 return {P[i] + 1, real_right};
2839 static const std::vector<uint64_t> highly_composites = {
2840 1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680,
2841 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440,
2842 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280,
2843 720720, 1081080, 1441440, 2162160, 2882880, 3603600, 4324320, 6486480,
2844 7207200, 8648640, 10810800, 14414400, 17297280, 21621600, 32432400,
2845 36756720, 43243200, 61261200, 73513440, 110270160, 122522400, 147026880,
2846 183783600, 245044800, 294053760, 367567200, 551350800, 698377680, 735134400,
2847 1102701600, 1396755360, 2095133040, 2205403200, 2327925600, 2793510720,
2848 3491888400, 4655851200, 5587021440, 6983776800, 10475665200, 13967553600,
2849 20951330400, 27935107200, 41902660800, 48886437600, 64250746560,
2850 73329656400, 80313433200, 97772875200, 128501493120, 146659312800,
2851 160626866400, 240940299600, 293318625600, 321253732800, 481880599200,
2852 642507465600, 963761198400, 1124388064800, 1606268664000, 1686582097200,
2853 1927522396800, 2248776129600, 3212537328000, 3373164194400, 4497552259200,
2854 6746328388800, 8995104518400, 9316358251200, 13492656777600, 18632716502400,
2855 26985313555200, 27949074753600, 32607253879200, 46581791256000,
2856 48910880818800, 55898149507200, 65214507758400, 93163582512000,
2857 97821761637600, 130429015516800, 195643523275200, 260858031033600,
2858 288807105787200, 391287046550400, 577614211574400, 782574093100800,
2859 866421317361600, 1010824870255200, 1444035528936000, 1516237305382800,
2860 1732842634723200, 2021649740510400, 2888071057872000, 3032474610765600,
2861 4043299481020800, 6064949221531200, 8086598962041600, 10108248702552000,
2862 12129898443062400, 18194847664593600, 20216497405104000, 24259796886124800,
2863 30324746107656000, 36389695329187200, 48519593772249600, 60649492215312000,
2864 72779390658374400, 74801040398884800, 106858629141264000,
2865 112201560598327200, 149602080797769600, 224403121196654400,
2866 299204161595539200, 374005201994424000, 448806242393308800,
2867 673209363589963200, 748010403988848000, 897612484786617600,
2868 1122015605983272000, 1346418727179926400, 1795224969573235200,
2869 2244031211966544000, 2692837454359852800, 3066842656354276800,
2870 4381203794791824000, 4488062423933088000, 6133685312708553600,
2871 8976124847866176000, 9200527969062830400, 12267370625417107200ULL,
2872 15334213281771384000ULL, 18401055938125660800ULL};
2873 return highly_composites;
2878 for (
int i =
static_cast<
int>(highly_composites().size()) - 1; i >= 0; --i)
2879 if (highly_composites()[i] <= right)
2880 return highly_composites()[i];
2882 throw detail::there_is_no_upto_error(
"highly composite number", right);
2888 if (right < left
or right < 2)
2889 throw detail::there_is_no_in_range_error(
"prime", left, right);
2890 left = std::max<uint64_t>(left, 2);
2891 auto [l_gap, r_gap] = prime_gap_upto(right);
2892 if (right - left + 1 <= r_gap - l_gap + 1) {
2894 std::vector<uint64_t> vals(right - left + 1);
2895 iota(vals.begin(), vals.end(), left);
2896 shuffle(vals.begin(), vals.end());
2897 for (uint64_t i : vals)
2900 throw detail::there_is_no_in_range_error(
"prime", left, right);
2905 n = next(left, right);
2913 tgen_ensure(left <= std::numeric_limits<uint64_t>::max() - 58,
2914 "math: invalid bound");
2915 for (uint64_t i = std::max<uint64_t>(2, left);; ++i)
2923 for (uint64_t i = right; i >= 2; --i)
2926 throw detail::there_is_no_upto_error(
"prime", right);
2933 for (
auto [p, e] : factor_by_prime(n))
2934 divisors *= (e + 1);
2942 int divisor_count) {
2944 "math: divisor count must be prime");
2945 int root = divisor_count - 1;
2946 uint64_t lo = detail::kth_root_floor(left, root);
2947 if (*detail::expo(lo, root, left) < left)
2949 uint64_t p =
gen_prime(lo
, detail::kth_root_floor(right, root)
);
2950 return *detail::expo(p, root, right);
2957 std::vector<uint64_t> rems,
2958 std::vector<uint64_t> mods) {
2960 throw detail::there_is_no_in_range_error(
"congruent number", left,
2963 "math: number of remainders and mods must be the same");
2964 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
2967 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
2969 "math: remainder must be smaller than the mod");
2970 crt = crt * detail::crt(rems[i], mods[i]);
2973 throw detail::there_is_no_in_range_error(
"congruent number", left,
2975 if (crt.m > right) {
2976 if (!(left <= crt.a
and crt.a <= right))
2977 throw detail::there_is_no_in_range_error(
"congruent number",
2980 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
2981 if (crt.a % mods[j] != rems[j])
2982 throw detail::there_is_no_in_range_error(
"congruent number",
2984 return static_cast<uint64_t>(crt.a);
2991 :
static_cast<uint64_t>(((left - crt.a) + crt.m - 1) / crt.m);
2992 uint64_t k_max =
static_cast<uint64_t>((right - crt.a) / crt.m);
2995 throw detail::there_is_no_in_range_error(
"congruent number", left,
2998 return static_cast<uint64_t>(crt.a + next(k_min, k_max) * crt.m);
3005 return gen_congruent(left, right, std::vector<uint64_t>({rem}),
3006 std::vector<uint64_t>({mod}));
3014 std::vector<uint64_t> mods) {
3016 "math: number of remainders and mods must be the same");
3017 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
3020 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
3022 "math: remainder must be smaller than the mod");
3023 crt = crt * detail::crt(rems[i], mods[i]);
3026 throw detail::there_is_no_from_error(
"congruent number", left);
3027 if (crt.m > std::numeric_limits<uint64_t>::max()) {
3029 throw detail::error(
3030 "math: congruent number does not exist or is too large");
3032 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
3033 if (crt.a % mods[j] != rems[j])
3034 throw detail::error(
"math: congruent number does "
3035 "not exist or is too large");
3036 return static_cast<uint64_t>(crt.a);
3042 k =
static_cast<uint64_t>(((left - crt.a) + crt.m - 1) / crt.m);
3043 detail::i128 result = crt.a + k * crt.m;
3045 if (result > std::numeric_limits<uint64_t>::max())
3046 throw detail::error(
"math: congruent number is too large");
3047 return static_cast<uint64_t>(result);
3053 return congruent_from(left, std::vector<uint64_t>{rem},
3054 std::vector<uint64_t>{mod});
3062 std::vector<uint64_t> mods) {
3064 "math: number of remainders and mods must be the same");
3065 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
3068 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
3070 "math: remainder must be smaller than the mod");
3072 crt = crt * detail::crt(rems[i], mods[i]);
3075 throw detail::there_is_no_upto_error(
"congruent number", right);
3076 if (crt.m > right) {
3077 if (!(crt.a <= right))
3078 throw detail::there_is_no_upto_error(
"congruent number", right);
3080 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
3081 if (crt.a % mods[j] != rems[j])
3082 throw detail::there_is_no_upto_error(
"congruent number",
3084 return static_cast<uint64_t>(crt.a);
3089 throw detail::there_is_no_upto_error(
"congruent number", right);
3091 uint64_t k =
static_cast<uint64_t>((right - crt.a) / crt.m);
3092 detail::i128 result = crt.a + k * crt.m;
3095 throw detail::there_is_no_upto_error(
"congruent number", right);
3096 return static_cast<uint64_t>(result);
3102 return congruent_upto(right, std::vector<uint64_t>{rem},
3103 std::vector<uint64_t>{mod});
3111 static const std::vector<uint64_t> fib = [] {
3112 std::vector<uint64_t> v = {0, 1};
3114 std::numeric_limits<uint64_t>::max() - v[v.size() - 2])
3115 v.push_back(v.back() + v[v.size() - 2]);
3127 std::optional<
int> part_right = std::nullopt) {
3128 if (!part_right.has_value())
3130 part_right = std::min(*part_right, n);
3132 "math: invalid parameters to gen_partition");
3133 tgen_ensure(part_left <= n
and *part_right > 0,
"math: no such partition");
3136 std::vector<
long double> dp(n + 1, detail::LOG_ZERO);
3137 dp[0] = detail::LOG_ONE;
3138 long double window = detail::LOG_ZERO;
3139 for (
int i = 1; i <= n; ++i) {
3141 window = detail::add_log_space(window, dp[i - part_left]);
3142 if (i >= *part_right + 1)
3143 window = detail::sub_log_space(window, dp[i - *part_right - 1]);
3146 tgen_ensure(dp[n] >= 0,
"math: no such partition");
3150 for (
int i = 1; i <= n; ++i)
3151 dp_pref[i] = detail::add_log_space(dp_pref[i - 1], dp[i]);
3153 std::vector<
int> part;
3157 int l = std::max(0, sum - *part_right), r = sum - part_left;
3158 detail::tgen_ensure_against_bug(r >= 0,
"math: r < 0 in gen_partition");
3160 int nxt_sum = std::min(sum, r);
3161 long double random = next<
long double>(0, 1);
3172 long double val_l = l ? dp_pref[l - 1] : detail::LOG_ZERO,
3174 while (nxt_sum > l
and
3175 dp_pref[nxt_sum - 1] >=
3178 random + (1 - random) * std::exp(
static_cast<
double>(
3182 part.push_back(sum - nxt_sum);
3195 std::optional<
int> part_right = std::nullopt) {
3196 if (!part_right.has_value())
3198 part_right = std::min(*part_right, n);
3200 "math: invalid parameters to gen_partition_fixed_size");
3201 tgen_ensure(
static_cast<
long long>(k) * part_left <= n
and
3202 n <=
static_cast<
long long>(k) * (*part_right),
3203 "math: no such partition");
3206 int s = n - k * part_left;
3208 std::vector<
int> part(k);
3209 if (*part_right == n) {
3211 std::vector<
int> cuts = {-1};
3213 int total = s + k - 1, bars = k - 1;
3214 for (
int i = 0; i < total
and bars > 0; ++i)
3215 if (next<
long double>(0, 1) <
3216 static_cast<
long double>(bars) / (total - i)) {
3220 cuts.push_back(total);
3223 for (
int i = 0; i < k; ++i)
3224 part[i] = cuts[i + 1] - cuts[i] - 1;
3227 int u = *part_right - part_left;
3230 std::vector<std::vector<
long double>> dp(
3231 k + 1, std::vector<
long double>(s + 1, detail::LOG_ZERO));
3232 dp[0][0] = detail::LOG_ONE;
3234 for (
int i = 1; i <= k; ++i) {
3235 std::vector<
long double> pref = dp[i - 1];
3236 for (
int j = 1; j <= s; ++j)
3237 pref[j] = detail::add_log_space(pref[j - 1], dp[i - 1][j]);
3239 for (
int j = 0; j <= s; ++j) {
3242 dp[i][j] = detail::sub_log_space(dp[i][j], pref[j - u - 1]);
3247 int left_to_distribute = s;
3248 for (
int i = k; i >= 1; --i) {
3249 long double log_total = detail::LOG_ZERO;
3250 for (
int j = 0; j <= u
and j <= left_to_distribute; ++j)
3251 log_total = detail::add_log_space(
3252 log_total, dp[i - 1][left_to_distribute - j]);
3253 detail::tgen_ensure_against_bug(
3254 log_total != detail::LOG_ZERO,
3255 "math: total == 0 in gen_partition_fixed_size");
3261 long double random =
3262 detail::log_space(next<
long double>(0, 1)) + log_total;
3264 long double cur_prob = detail::LOG_ZERO;
3266 for (
int j = 0; j <= u
and j <= left_to_distribute; ++j) {
3267 cur_prob = detail::add_log_space(
3268 cur_prob, dp[i - 1][left_to_distribute - j]);
3269 if (random < cur_prob) {
3275 part[k - i] = chosen;
3276 left_to_distribute -= chosen;
3293 uint64_t n,
int k, uint64_t part_left = 0,
3294 std::optional<uint64_t> part_right = std::nullopt) {
3295 if (!part_right.has_value())
3297 part_right = std::min(*part_right, n);
3299 detail::u128 n128 = n;
3300 detail::u128 k128 = k;
3301 detail::u128 part_left128 = part_left;
3302 detail::u128 part_right128 = *part_right;
3305 "math: invalid parameters to gen_partition_fixed_size_fast");
3307 k128 * part_left128 <= n128
and
3308 k128 * part_right128 >= n128,
3309 "math: no such partition");
3311 uint64_t slack_total =
static_cast<uint64_t>(n128 - k128 * part_left128);
3312 uint64_t slack_max =
static_cast<uint64_t>(part_right128 - part_left128);
3314 std::vector<uint64_t> part(k);
3316 part[0] = slack_total;
3318 std::vector<uint64_t> cuts(k - 1);
3319 for (uint64_t &d : cuts)
3320 d = next<uint64_t>(0, slack_total);
3321 std::sort(cuts.begin(), cuts.end());
3324 for (
int i = 0; i + 1 < k; ++i) {
3325 part[i] = cuts[i] - prev;
3328 part[k - 1] = slack_total - prev;
3331 auto add_part_left = [part_left](uint64_t x) -> uint64_t {
3332 detail::u128 val = x + part_left;
3333 detail::tgen_ensure_against_bug(
3334 val <= std::numeric_limits<uint64_t>::max(),
3335 "math: part + part_left exceeds uint64_t in "
3336 "gen_partition_fixed_size_fast");
3337 return static_cast<uint64_t>(val);
3340 if (slack_max >= slack_total) {
3341 for (uint64_t &x : part)
3342 x = add_part_left(x);
3346 detail::u128 remaining = 0;
3347 for (uint64_t &x : part) {
3348 if (x > slack_max) {
3349 remaining += x - slack_max;
3352 x = add_part_left(x);
3355 if (remaining > 0) {
3356 for (uint64_t &x : part) {
3357 if (x < *part_right && remaining > 0) {
3358 detail::u128 room = *part_right - x;
3359 detail::u128 add = std::min(remaining, room);
3360 detail::u128 val = x + add;
3361 detail::tgen_ensure_against_bug(
3363 "math: part exceeds part_right after redistribution in "
3364 "gen_partition_fixed_size_fast");
3365 x =
static_cast<uint64_t>(val);
3369 detail::tgen_ensure_against_bug(
3370 remaining == 0,
"math: remaining mass after redistribution in "
3371 "gen_partition_fixed_size_fast");
3381template <
typename T>
3384 std::optional<uint64_t> max_size = std::nullopt) {
3385 size_t n = elements.size();
3386 tgen_ensure(k > 0,
"math: partition_elements: k must be positive");
3388 "math: partition_elements: min_size must be non-negative");
3390 std::vector<uint64_t> sizes;
3391 if (max_size.has_value()) {
3392 sizes = gen_partition_fixed_size_fast(n, k, min_size, max_size);
3395 gen_partition_fixed_size(
static_cast<
int>(n), k, min_size))
3396 sizes.push_back(sz);
3399 std::vector<std::vector<T>> groups;
3402 for (uint64_t sz : sizes) {
3403 groups.emplace_back(elements.begin() + pos,
3404 elements.begin() + pos + sz);
3413
3414
3415
3416
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3459 std::vector<regex_node> children_;
3460 int left_bound_, right_bound_;
3463 log_space_num_ways_;
3468 regex_node(
const std::string &pattern)
3469 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3470 if (pattern.size() == 1) {
3471 log_space_num_ways_ = math::detail::LOG_ONE;
3474 tgen_ensure_against_bug(pattern[0] ==
'[' and pattern.back() ==
']',
3475 "str: invalid regex: expected character class");
3476 int size =
static_cast<
int>(pattern.size()) - 2;
3477 log_space_num_ways_ =
3478 static_cast<
double>(math::detail::log_space(size));
3479 distinct_ = distinct_container<
char>(pattern.substr(1, size));
3482 regex_node(
const std::string &pattern, std::vector<regex_node> &children)
3483 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3484 if (pattern ==
"SEQ") {
3486 log_space_num_ways_ = math::detail::LOG_ONE;
3487 for (
const auto &child : children)
3488 log_space_num_ways_ += child.log_space_num_ways_;
3489 }
else if (pattern ==
"OR") {
3491 log_space_num_ways_ = math::detail::LOG_ZERO;
3492 for (
const auto &child : children)
3493 log_space_num_ways_ =
3494 static_cast<
double>(math::detail::add_log_space(
3495 log_space_num_ways_, child.log_space_num_ways_));
3497 tgen_ensure_against_bug(
"str: invalid regex: expected SEQ or OR");
3499 children_ = std::move(children);
3503 regex_node(
int left_bound,
int right_bound, regex_node &child)
3504 : pattern_(
"REP"), left_bound_(left_bound), right_bound_(right_bound) {
3505 log_space_num_ways_ = math::detail::LOG_ZERO;
3506 for (
int i = left_bound; i <= right_bound; ++i)
3507 log_space_num_ways_ =
3508 static_cast<
double>(math::detail::add_log_space(
3509 log_space_num_ways_, i * child.log_space_num_ways_));
3511 children_.push_back(std::move(child));
3517 std::vector<regex_node> cur;
3518 std::vector<regex_node> branches;
3522inline regex_node make_regex_seq(regex_state &st) {
3523 return regex_node(
"SEQ", st.cur);
3527inline regex_node finish_regex_state(regex_state &st) {
3529 if (st.branches.empty())
3530 return make_regex_seq(st);
3533 st.branches.push_back(make_regex_seq(st));
3534 return regex_node(
"OR", st.branches);
3539inline regex_node parse_regex(std::string regex) {
3540 std::string new_regex;
3541 for (
char c : regex)
3544 swap(regex, new_regex);
3546 std::vector<regex_state> stack;
3548 for (size_t i = 0; i < regex.size(); ++i) {
3553 stack.push_back(std::move(cur));
3554 cur = regex_state();
3555 }
else if (c ==
')') {
3557 regex_node node = finish_regex_state(cur);
3559 tgen_ensure(!stack.empty(),
"str: invalid regex: unmatched `)`");
3560 cur = std::move(stack.back());
3563 cur.cur.push_back(std::move(node));
3564 }
else if (c ==
'|') {
3566 regex_node node = make_regex_seq(cur);
3567 cur.branches.push_back(std::move(node));
3568 }
else if (c ==
'[') {
3572 for (++i; i < regex.size()
and regex[i] !=
']'; ++i) {
3573 if (i + 2 < regex.size()
and regex[i + 1] ==
'-') {
3574 char a = regex[i], b = regex[i + 2];
3577 for (
char x = a; x <= b; ++x)
3585 "str: invalid regex: unmatched `[`");
3586 cur.cur.emplace_back(
"[" + chars +
"]");
3587 }
else if (c ==
'{') {
3592 while (i < regex.size()
and
3593 isdigit(
static_cast<
unsigned char>(regex[i]))) {
3597 "str: invalid regex: number too large inside `{}`");
3598 l = 10 * l + (regex[i] -
'0');
3602 if (i < regex.size()
and regex[i] ==
',') {
3604 while (i < regex.size()
and
3605 isdigit(
static_cast<
unsigned char>(regex[i]))) {
3609 r <=
static_cast<
int>(1e8),
3610 "str: invalid regex: number too large inside `{}`");
3611 r = 10 * r + (regex[i] -
'0');
3618 "str: invalid regex: unmatched `{`");
3620 "str: invalid regex: missing number inside `{}`");
3622 "str: invalid regex: invalid range inside `{}`");
3626 "str: invalid regex: expected expression before `{}`");
3628 regex_node rep(l, r, cur.cur.back());
3630 cur.cur.push_back(std::move(rep));
3633 cur.cur.emplace_back(std::string(1, c));
3637 tgen_ensure(stack.empty(),
"str: invalid regex: unmatched `(`");
3638 return finish_regex_state(cur);
3642inline void gen_regex(
const regex_node &node, std::string &str) {
3644 if (node.pattern_[0] ==
'[') {
3645 str += node.pattern_[1 + next<
int>(
3646 0,
static_cast<
int>(node.pattern_.size()) -
3652 if (node.left_bound_ != -1) {
3657 static_cast<
double>(math::detail::log_space(next<
double>(0, 1))) +
3658 node.log_space_num_ways_;
3659 double cur_prob = math::detail::LOG_ZERO;
3660 double child_num_ways = node.children_[0].log_space_num_ways_;
3662 for (
int i = node.left_bound_; i <= node.right_bound_; ++i) {
3663 cur_prob =
static_cast<
double>(
3664 math::detail::add_log_space(cur_prob, i * child_num_ways));
3665 if (log_rand <= cur_prob) {
3666 for (
int j = 0; j < i; ++j)
3667 gen_regex(node.children_[0], str);
3672 tgen_ensure_against_bug(
false,
3673 "str: log_rand > cur_prob in REP gen_regex");
3677 if (!node.children_.empty()
and node.pattern_ ==
"SEQ") {
3678 for (
const regex_node &child : node.children_)
3679 gen_regex(child, str);
3684 if (!node.children_.empty()
and node.pattern_ ==
"OR") {
3689 static_cast<
double>(math::detail::log_space(next<
double>(0, 1))) +
3690 node.log_space_num_ways_;
3691 double cur_prob = math::detail::LOG_ZERO;
3693 for (
const regex_node &child : node.children_) {
3694 cur_prob =
static_cast<
double>(math::detail::add_log_space(
3695 cur_prob, child.log_space_num_ways_));
3696 if (log_rand <= cur_prob) {
3697 gen_regex(child, str);
3702 tgen_ensure_against_bug(
false,
3703 "str: log_rand > cur_prob in OR gen_regex");
3707 detail::tgen_ensure_against_bug(
3708 node.pattern_.size() == 1,
3709 "str: invalid regex: expected single character, but got `" +
3710 node.pattern_ +
"`");
3711 str += node.pattern_[0];
3715template <
typename... Args>
3716std::string regex_format(
const std::string &s, Args &&...args) {
3717 if constexpr (
sizeof...(Args) == 0) {
3720 int size = std::snprintf(
nullptr, 0, s.c_str(), args...) + 1;
3721 std::string buf(size,
'\0');
3722 std::snprintf(buf.data(), size, s.c_str(), args...);
3731
3732
3735 std::optional<
list<
char>> list_;
3736 std::optional<detail::regex_node>
3741 str(
int size,
char value_left =
'a',
char value_right =
'z') {
3742 tgen_ensure(size > 0,
"str: size must be positive");
3743 list_ = list<
char>(size, value_left, value_right);
3748 str(
int size, std::set<
char> chars) {
3749 tgen_ensure(size > 0,
"str: size must be positive");
3750 list_ = list<
char>(size, chars);
3754 template <
typename... Args>
str(
const std::string ®ex, Args &&...args) {
3755 tgen_ensure(regex.size() > 0,
"str: regex must be non-empty");
3757 root_ = detail::parse_regex(
3758 detail::regex_format(regex, std::forward<Args>(args)...));
3763 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3764 list_->fix(idx, character);
3770 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3771 list_->equal(indices);
3777 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3778 list_->equal(idx_1, idx_2);
3784 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3785 list_->equal_range(left, right);
3791 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3798 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3799 tgen_ensure(0 <= left
and left <= right
and right < list_->size_,
3800 "str: range indices must be valid");
3801 for (
int i = left; i < right - (i - left); ++i)
3808 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3809 return palindrome(0, list_->size_ - 1);
3815 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3816 list_->different(indices);
3822 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3823 list_->different(idx_1, idx_2);
3829 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3830 list_->different_range(left, right);
3836 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3837 list_->all_different();
3843 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3844 list_->adjacent_different();
3850 using tgen_is_sequential_tag = detail::is_sequential_tag;
3852 using value_type =
char;
3853 using std_type = std::string;
3856 value(
const std::string &str) : str_(str) {
3857 tgen_ensure(!str_.empty(),
"str: value: cannot be empty");
3861 int size()
const {
return static_cast<
int>(str_.size()); }
3866 "str: value: index out of bounds");
3869 const char &operator[](
int idx)
const {
3871 "str: value: index out of bounds");
3878 std::sort(str_.begin(), str_.end());
3885 std::reverse(str_.begin(), str_.end());
3892 for (
char &c : str_)
3893 c =
static_cast<
char>(
3894 std::tolower(
static_cast<
unsigned char>(c)));
3901 for (
char &c : str_)
3902 c =
static_cast<
char>(
3903 std::toupper(
static_cast<
unsigned char>(c)));
3910 return value(str_ + rhs.str_
);
3916 for (
int i = 0; i < size(); ++i)
3917 std::swap(str_[i], str_[next(0, size() - 1)]);
3927 template <
typename Dist>
3930 "value and distribution must have the same size");
3931 return str_[next_by_distribution(distribution)];
3933 template <
typename Dist>
3934 char pick_by_distribution(
3935 const std::initializer_list<Dist> &distribution)
const {
3936 return pick_by_distribution(std::vector<Dist>(distribution));
3943 "number of elements to choose must be valid");
3944 std::string new_str;
3946 for (
int i = 0; need > 0; ++i) {
3948 if (next(1, left) <= need) {
3949 new_str.push_back(str_[i]);
3957 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
3958 return out << val.str_;
3962 std::string
to_std()
const {
return std_type(str_); }
3971 std::string ret_str;
3972 gen_regex(*root_, ret_str);
3976 std::vector<
char> vec = list_->gen().to_std();
3977 return value(std::string(vec.begin(), vec.end()));
3983
3984
3985
3986
3992template <
typename T> std::pair<T, T> gen_eq(T L1, T R1, T L2, T R2) {
3993 T L = std::max(L1, L2);
3994 T R = std::min(R1, R2);
3996 tgen_ensure(L <= R,
"pair: no valid values to generate");
3997 T x = next<T>(L, R);
4002template <
typename T>
4003std::pair<u128, u128> get_n_and_m(T L1, T R1, T L2, T R2) {
4004 u128 n =
static_cast<i128>(R1) - L1 + 1;
4005 u128 m =
static_cast<i128>(R2) - L2 + 1;
4011static u128 pos_arith_sum(u128 first, u128 last, u128 num_terms) {
4012 u128 x = first + last, y = num_terms;
4025template <
typename T> std::pair<T, T> gen_neq(T L1, T R1, T L2, T R2) {
4026 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4028 T L_intersect = std::max(L1, L2);
4029 T R_intersect = std::min(R1, R2);
4030 u128 inter =
static_cast<i128>(R_intersect) - L_intersect + 1;
4032 u128 total = n * m - inter;
4033 tgen_ensure(total > 0,
"pair: no valid values to generate");
4038 a = next<T>(L1, R1);
4039 b = next<T>(L2, R2);
4050template <
typename T>
4051std::pair<u128, u128> count_lt_regions(T L1, T R1, T L2, T R2) {
4052 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4055 i128 L_second = std::max<i128>(L2,
static_cast<i128>(L1) + 1);
4059 i128 split = std::min<i128>(R_second, R1);
4062 u128 len1 = std::max<i128>(0, split - L_second + 1);
4064 u128 count_region1 = 0;
4067 i128 first = L_second - L1;
4068 i128 last = split - L1;
4071 count_region1 = pos_arith_sum(first, last, len1);
4076 i128 L_second_region2 = std::max(L_second,
static_cast<i128>(R1) + 1);
4078 u128 len2 = std::max<i128>(0, R_second - L_second_region2 + 1);
4079 u128 count_region2 = len2 * n;
4081 return {count_region1, count_region2};
4086template <
typename T> std::pair<T, T> gen_lt(T L1, T R1, T L2, T R2) {
4087 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4091 i128 L_second = std::max<i128>(L2,
static_cast<i128>(L1) + 1);
4097 i128 split = std::min<i128>(R_second, R1);
4099 auto [count_region1, count_region2] = count_lt_regions(L1, R1, L2, R2);
4100 u128 total = count_region1 + count_region2;
4101 tgen_ensure(total > 0,
"pair: no valid values to generate");
4103 u128 k = detail::next128(total);
4104 if (k < count_region1) {
4108 u128 len1 = std::max<i128>(0, split - L_second + 1);
4115 i128 base = L_second - L1;
4116 i128 lo = 0, hi =
static_cast<i128>(len1) - 1;
4119 i128 mid = lo + (hi - lo) / 2;
4121 if (pos_arith_sum(base, base + mid, mid + 1) <= k)
4130 k -= pos_arith_sum(base, base + d - 1, d);
4132 return {L1 +
static_cast<T>(k), L_second + d};
4138 i128 L_second_region2 = std::max(L_second,
static_cast<i128>(R1) + 1);
4140 return {L1 +
static_cast<T>(k % n),
4141 L_second_region2 +
static_cast<T>(k / n)};
4147template <
typename T> std::pair<T, T> gen_gt(T L1, T R1, T L2, T R2) {
4148 auto [first, second] = gen_lt(L2, R2, L1, R1);
4149 return {second, first};
4154template <
typename T> std::pair<T, T> gen_leq(T L1, T R1, T L2, T R2) {
4156 i128 L_intersect = std::max(L1, L2);
4157 i128 R_intersect = std::min(R1, R2);
4158 u128 eq_count = std::max<i128>(0, R_intersect - L_intersect + 1);
4161 auto [lt_region1, lt_region2] = count_lt_regions(L1, R1, L2, R2);
4162 u128 lt_count = lt_region1 + lt_region2;
4164 u128 total = eq_count + lt_count;
4165 tgen_ensure(total > 0,
"pair: no valid values to generate");
4167 if (detail::next128(total) < eq_count)
4168 return gen_eq(L1, R1, L2, R2);
4169 return gen_lt(L1, R1, L2, R2);
4174template <
typename T> std::pair<T, T> gen_geq(T L1, T R1, T L2, T R2) {
4175 auto [first, second] = gen_leq(L2, R2, L1, R1);
4176 return {second, first};
4182
4183
4184
4185
4188 std::pair<T, T> first_, second_;
4190 enum class restriction_type { eq, neq, lt, gt, leq, geq, unspecified };
4191 restriction_type type_ = restriction_type::unspecified;
4195 pair(T first_left, T first_right, T second_left, T second_right)
4196 : first_(first_left, first_right), second_(second_left, second_right) {
4198 "pair: first range must be valid");
4200 "pair: second range must be valid");
4205 :
pair(both_left, both_right, both_left, both_right) {}
4209 type_ = restriction_type::eq;
4215 type_ = restriction_type::neq;
4221 type_ = restriction_type::lt;
4227 type_ = restriction_type::gt;
4233 type_ = restriction_type::leq;
4239 type_ = restriction_type::geq;
4245 using value_type = T;
4246 using std_type = std::pair<T, T>;
4248 std::pair<T, T> pair_;
4251 value(
const std::pair<T, T> &pair) : pair_(pair), sep_(
' ') {}
4253 : pair_(first, second), sep_(
' ') {}
4265 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
4266 return out << val.pair_.first << val.sep_ << val.pair_.second;
4271 if constexpr (!detail::is_generator_value<T>::value) {
4274 std::pair<
typename T::std_type,
typename T::std_type> pair(
4275 pair_.first.to_std(), pair_.second.to_std());
4284 T L1 = first_.first, R1 = first_.second;
4285 T L2 = second_.first, R2 = second_.second;
4288 case restriction_type::unspecified:
4289 return {next<T>(L1, R1), next<T>(L2, R2)};
4290 case restriction_type::eq:
4291 return detail::gen_eq<T>(L1, R1, L2, R2);
4292 case restriction_type::neq:
4293 return detail::gen_neq<T>(L1, R1, L2, R2);
4294 case restriction_type::lt:
4295 return detail::gen_lt<T>(L1, R1, L2, R2);
4296 case restriction_type::gt:
4297 return detail::gen_gt<T>(L1, R1, L2, R2);
4298 case restriction_type::leq:
4299 return detail::gen_leq<T>(L1, R1, L2, R2);
4300 case restriction_type::geq:
4301 return detail::gen_geq<T>(L1, R1, L2, R2);
4303 throw detail::error(
"pair: unknown restriction type");
4308
4309
4310
4311
4317inline std::vector<std::pair<
int,
int>> edges_from_prufer(std::vector<
int> p) {
4318 int n =
static_cast<
int>(p.size()) + 2;
4321 std::vector<
int> d(n, 1);
4330 idx = u =
static_cast<
int>(find(d.begin(), d.end(), 1) - d.begin());
4333 std::vector<std::pair<
int,
int>> edges;
4335 edges.emplace_back(u, v);
4336 if (--d[v] == 1
and v < idx)
4339 idx = u =
static_cast<
int>(find(d.begin() + idx + 1, d.end(), 1) -
4347 std::vector<
int> parent_;
4348 std::vector<
unsigned char> rank_;
4353 dsu(
int n) : parent_(n), rank_(n, 0) {
4354 for (
int i = 0; i < n; ++i)
4360 void add_elements(
int k) {
4361 for (
int i = 0; i < k; ++i) {
4362 int new_id =
static_cast<
int>(parent_.size());
4363 parent_.push_back(new_id);
4371 return parent_[i] == i ? i : parent_[i] = find(parent_[i]);
4377 bool unite(
int a,
int b) {
4382 if (rank_[a] > rank_[b])
4385 if (rank_[a] == rank_[b])
4394template <
typename VWeight,
typename EWeight>
struct wgraph;
4397
4398
4399
4400
4401
4402
4403
4404
4406template <
typename VWeight,
typename EWeight>
4409 std::set<std::pair<
int,
int>> edges_;
4414 tgen_ensure(n > 0,
"wtree: number of vertices must be positive");
4420 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n_,
4421 "wtree: vertices must be indexed in [0, n)");
4422 tgen_ensure(u != v,
"wtree: cannot add self loop to tree");
4426 edges_.emplace(u, v);
4438 std::vector<std::set<
int>> adj_;
4439 std::vector<std::pair<
int,
int>> edges_;
4440 bool print_1_based_;
4442 std::optional<
int> print_parents_;
4444 std::optional<std::vector<VWeight>> vertex_weights_;
4445 std::optional<std::vector<EWeight>>
4451 value(
const std::vector<std::set<
int>> &adj)
4452 : n_(
static_cast<
int>(adj.size())),
adj_(
adj),
4453 print_1_based_(
false), print_n_(
false),
dsu_(
n_) {
4454 for (
int u = 0; u < n_; ++u)
4455 for (
auto v : adj[u]) {
4458 "wtree: value: vertices must be indexed in [0, n)");
4461 edges_.emplace_back(u, v);
4464 "wtree: value: initial graph must form a tree");
4471 value(
int n,
const std::vector<std::pair<
int,
int>> &edges)
4472 : n_(n),
adj_(
n), print_1_based_(
false), print_n_(
false),
dsu_(
n) {
4473 edges_.reserve(edges.size());
4474 for (
auto [u, v] : edges) {
4475 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n,
4476 "wtree: value: vertices must be indexed in [0, n)");
4478 "wtree: value: initial graph must form a tree");
4481 edges_.emplace_back(u, v);
4486 value(
int n,
const std::set<std::pair<
int,
int>> &edges)
4489 value(
int n,
const std::initializer_list<std::pair<
int,
int>> &edges)
4490 : value(n, std::vector<std::pair<
int,
int>>(edges)) {}
4495 value(
const typename wgraph<VWeight, EWeight>::value &g);
4499 template <
typename NewVWeight,
typename NewEWeight>
4500 typename wtree<NewVWeight, NewEWeight>::value
4501 convert_weight_types()
const {
4503 !edge_weights_.has_value(),
4504 "wtree: value: cannot convert weight type after "
4505 "assigning weights");
4507 typename wtree<NewVWeight, NewEWeight>::value new_tree(adj_);
4508 new_tree.print_1_based_ = print_1_based_;
4509 new_tree.print_n_ = print_n_;
4510 new_tree.print_parents_ = print_parents_;
4515 int n()
const {
return n_; }
4525 return vertex_weights_;
4530 return edge_weights_;
4535 template <
typename NewVWeight = VWeight>
4537 const std::vector<NewVWeight> &vertex_weights)
const {
4539 "wtree: value: must give `n` vertex weights");
4541 auto new_tree = convert_weight_types<NewVWeight, EWeight>();
4542 new_tree.vertex_weights_ = vertex_weights;
4548 template <
typename NewEWeight = EWeight>
4552 edge_weights.size() == edges().size(),
4553 "wtree: value: must give `edges().size()` edge weights");
4555 auto new_tree = convert_weight_types<VWeight, NewEWeight>();
4556 new_tree.edge_weights_ = edge_weights;
4564 "wtree: value: edge_weighted requires a tree with no "
4567 "wtree: value: tree is already edge-weighted");
4569 edge_weights_ = std::vector<EWeight>();
4577 print_1_based_ =
true;
4594 "wtree: value: root must be -1, `n`, or in [0, n)");
4595 print_parents_ = root;
4608 std::vector<
int> new_label(
n());
4609 std::vector<
int> shuffled;
4610 for (
int i = 0; i <
n(); ++i) {
4611 if (indices.count(i))
4614 shuffled.push_back(i);
4616 std::vector<
int> targets = shuffled;
4617 tgen::shuffle(targets.begin(), targets.end());
4618 for (size_t k = 0; k < shuffled.size(); ++k)
4619 new_label[shuffled[k]] = targets[k];
4622 std::vector<std::set<
int>> new_adj(
n());
4623 for (
int u = 0; u < n(); ++u)
4624 for (
int v : adj_[u])
4625 new_adj[new_label[u]].insert(new_label[v]);
4626 adj_ = std::move(new_adj);
4629 for (
auto &[u, v] : edges_) {
4637 if (vertex_weights_.has_value()) {
4638 std::vector<VWeight> new_vw(
n());
4639 for (
int i = 0; i < n(); ++i)
4640 new_vw[new_label[i]] = (*vertex_weights_)[i];
4641 vertex_weights_ = std::move(new_vw);
4645 dsu_ = detail::dsu(n());
4646 for (
auto [u, v] : edges_)
4651 std::vector<
int> perm(edges_.size());
4652 std::iota(perm.begin(), perm.end(), 0);
4653 tgen::shuffle(perm.begin(), perm.end());
4655 std::vector<std::pair<
int,
int>> new_edges;
4656 std::optional<std::vector<EWeight>> new_ew;
4657 if (edge_weights_.has_value())
4658 new_ew = std::vector<EWeight>();
4659 for (
int i : perm) {
4660 new_edges.push_back(edges_[i]);
4661 if (new_ew.has_value())
4662 new_ew->push_back((*edge_weights_)[i]);
4665 if (new_ew.has_value())
4666 edge_weights_ = new_ew;
4677 value &add_edge(
int u,
int v, std::optional<EWeight> w = std::nullopt) {
4679 "wtree: value: vertex ids must be valid");
4684 if (adj_[u].count(v))
4689 edges_.emplace_back(u, v);
4691 "wtree: value: added edge must not create a cycle");
4693 if (w.has_value()) {
4695 "wtree: value: cannot add weighted edge to "
4696 "edge-unweighted tree");
4698 edge_weights_->push_back(*w);
4701 "wtree: value: cannot add unweighted edge to "
4702 "edge-weighted tree");
4712 std::optional<EWeight> new_w = std::nullopt) {
4715 "wtree: value: vertex ids must be valid");
4719 add_vertices(rhs.n(), rhs.vertex_weights());
4720 for (
int i = 0; i <
static_cast<
int>(rhs.edges().size()); ++i) {
4721 auto [u, v] = rhs.edges()[i];
4722 add_edge(shift + u, shift + v,
4723 rhs.edge_weights().has_value()
4724 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4729 add_edge(new_u, shift + new_v, new_w);
4739 std::set<std::pair<
int,
int>> index_pairs) {
4741 std::set<
int> idx_left, idx_right;
4742 std::vector<
int> right_id_to_left(rhs
.n(), -1);
4743 for (
auto [l, r] : index_pairs) {
4745 0 <= l
and l < n()
and 0 <= r
and r < rhs.n(),
4746 "wtree: value: vertex indices to glue must be valid");
4747 tgen_ensure(idx_left.count(l) == 0
and idx_right.count(r) == 0,
4748 "wtree: value: must not have repeated indices "
4749 "on the same side to glue");
4752 idx_right.insert(r);
4753 right_id_to_left[r] = l;
4757 std::vector<
int> new_right_id(rhs
.n(), -1);
4758 int intersection_lt = 0;
4759 std::optional<std::vector<VWeight>> rhs_vertex_weights;
4760 for (
int i = 0; i < rhs
.n(); ++i) {
4761 if (right_id_to_left[i] != -1) {
4764 new_right_id[i] = right_id_to_left[i];
4767 new_right_id[i] =
n() + i - intersection_lt;
4768 if (rhs.vertex_weights().has_value()) {
4769 if (!rhs_vertex_weights.has_value())
4770 rhs_vertex_weights = std::vector<VWeight>();
4771 rhs_vertex_weights->push_back(
4772 (*rhs.vertex_weights())[i]);
4778 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
4779 for (
int i = 0; i <
static_cast<
int>(rhs.edges().size()); ++i) {
4780 auto [u, v] = rhs.edges()[i];
4781 add_edge(new_right_id[u], new_right_id[v],
4782 rhs.edge_weights().has_value()
4783 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4790 std::initializer_list<std::pair<
int,
int>> il) {
4791 return glue(rhs, std::set<std::pair<
int,
int>>(il));
4799 std::set<std::pair<
int,
int>> index_pairs;
4800 for (
auto i : indices)
4801 index_pairs.emplace(i, i);
4802 return glue(rhs, index_pairs);
4804 value &glue(
const value &rhs,
const std::initializer_list<
int> &il) {
4805 return glue(rhs, std::set<
int>(il));
4810 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
4812 out << val.n() <<
'\n';
4815 if (val.vertex_weights()) {
4816 for (
int i = 0; i < val.n(); ++i) {
4819 out << (*val.vertex_weights())[i];
4824 tgen_ensure(
static_cast<
int>(val.edges().size()) == val.n() - 1,
4825 "wtree: value: invalid tree to print (number of edges "
4826 "must be `n` - 1)");
4829 if (val.print_parents_.has_value()) {
4831 "wtree: value: cannot print parent style if edges "
4834 int root = *val.print_parents_;
4835 bool skip_parent_0 = root == -1;
4838 if (root == val.n())
4839 root = next(0, val.n() - 1);
4841 std::vector<
int> parent(val.n(), -1);
4844 std::vector<
int> vis(val.n(),
false);
4851 for (
int v : val.adj()[u])
4859 if (skip_parent_0) {
4860 for (
int i = 1; i < val.n(); ++i) {
4863 "wtree: value: parent of i must be less than i for "
4864 "printing in parent style if root is -1");
4868 out << parent[i] + val.print_1_based_;
4871 for (
int i = 0; i < val.n(); ++i) {
4874 out << (parent[i] == -1 ? -1 : parent[i]) +
4884 for (
int i = 0; i <
static_cast<
int>(val.edges().size()); ++i) {
4885 auto [u, v] = val.edges()[i];
4886 out << (u + val.print_1_based_) <<
" "
4887 << (v + val.print_1_based_);
4890 if (val.edge_weights().has_value())
4891 out <<
" " << (*val.edge_weights())[i];
4902 return std_type(n_, adj_);
4908 std::vector<std::set<
int>> adj(n_ + 1);
4909 for (
int u = 0; u < n_; ++u)
4910 for (
int v : adj_[u])
4911 adj[u + 1].insert(v + 1);
4912 return std_type(n_, adj);
4919 value &add_vertices(
int k, std::optional<std::vector<VWeight>>
4920 new_vertex_weights = std::nullopt) {
4923 if (new_vertex_weights.has_value()) {
4925 "wtree: value: cannot add weighted vertices to "
4926 "vertex-unweighted tree");
4928 static_cast<
int>(new_vertex_weights->size()) == k,
4929 "wtree: value: number of vertex weights must be equal "
4930 "to number of added vertices");
4932 vertex_weights_->insert(vertex_weights_->end(),
4933 new_vertex_weights->begin(),
4934 new_vertex_weights->end());
4937 "wtree: value: cannot add unweighted vertices to "
4938 "vertex-weighted tree");
4940 dsu_.add_elements(k);
4950 std::vector<std::vector<
int>> adj(n_);
4951 for (
auto [u, v] : edges_) {
4952 adj[u].push_back(v);
4953 adj[v].push_back(u);
4956 std::vector<
int> comp_size;
4957 std::vector<std::vector<
int>> component_ids;
4958 std::vector<
bool> vis(n_,
false);
4961 for (
int i = 0; i < n_; ++i) {
4967 comp_size.push_back(0);
4968 component_ids.emplace_back();
4973 component_ids.back().push_back(u);
4974 for (
int v : adj[u]) {
4985 std::vector<std::pair<
int,
int>> new_edges(edges_.begin(),
4987 if (comp_size.size() > 1) {
4988 std::vector<
int> prufer_values = many_by_distribution(
4989 static_cast<
int>(comp_size.size()) - 2, comp_size);
4990 for (
auto [u, v] : detail::edges_from_prufer(prufer_values))
4991 new_edges.emplace_back(pick(component_ids[u]),
4992 pick(component_ids[v]));
4995 return value(n_, new_edges);
5006 std::vector<std::pair<
int,
int>> edges;
5007 for (
int i = 1; i < n; ++i)
5008 edges.emplace_back(i, wnext<
int>(i, elongation));
5009 return value(n, edges);
5016 tgen_ensure(n > 0,
"wtree: gen_kruskal: n must be positive");
5018 return value(1, {});
5020 detail::dsu components(n);
5021 std::vector<std::pair<
int,
int>> edges;
5022 edges.reserve(n - 1);
5023 while (edges.size() < size_t(n - 1)) {
5024 int u = next(0, n - 1);
5025 int v = next(0, n - 1);
5028 if (components.unite(u, v))
5029 edges.emplace_back(u, v);
5031 return value(n, edges);
5036
5037
5049
5050
5051
5052
5058inline uint64_t undirected_edge_key(
int u,
int v) {
5061 return (
static_cast<uint64_t>(u) << 32) |
5062 static_cast<uint64_t>(
static_cast<uint32_t>(v));
5067inline uint64_t directed_edge_key(
int u,
int v) {
5068 return (
static_cast<uint64_t>(u) << 32) |
5069 static_cast<uint64_t>(
static_cast<uint32_t>(v));
5074inline long long max_graph_edges(
int n,
bool directed,
bool self_loops) {
5078 return self_loops ?
static_cast<
long long>(n) * n
5079 :
static_cast<
long long>(n) * (n - 1);
5080 return self_loops ?
static_cast<
long long>(n) * (n + 1) / 2
5081 :
static_cast<
long long>(n) * (n - 1) / 2;
5086inline std::pair<
int,
int> get_random_graph_edge(
int n,
bool directed,
5090 return {next<
int>(0, n - 1), next<
int>(0, n - 1)};
5091 int u = next<
int>(0, n - 1);
5092 int v = next<
int>(0, n - 1);
5094 v = next<
int>(0, n - 1);
5098 int u = next<
int>(0, n - 1);
5099 int v = next<
int>(0, n - 1);
5104 int u = next<
int>(0, n - 1);
5105 int v = next<
int>(0, n - 1);
5107 v = next<
int>(0, n - 1);
5116inline std::pair<
int,
int> decode_undirected_simple_edge(
int n,
long long idx) {
5117 auto base = [&](
int u) ->
long long {
5118 return static_cast<
long long>(u) * (n - 1) -
5119 static_cast<
long long>(u) * (u - 1) / 2;
5121 int lo = 0, hi = n - 2;
5123 int mid = (lo + hi + 1) / 2;
5124 if (base(mid) <= idx)
5129 return {lo, lo + 1 +
int(idx - base(lo))};
5135inline std::pair<
int,
int> decode_undirected_loops_edge(
int n,
long long idx) {
5136 auto base = [&](
int u) ->
long long {
5137 return static_cast<
long long>(u) * n -
5138 static_cast<
long long>(u) * (u - 1) / 2;
5140 int lo = 0, hi = n - 1;
5142 int mid = (lo + hi + 1) / 2;
5143 if (base(mid) <= idx)
5148 return {lo, lo +
int(idx - base(lo))};
5153inline std::pair<
int,
int> decode_directed_simple_edge(
int n,
long long idx) {
5154 int u =
static_cast<
int>(idx / (n - 1));
5155 int rem =
static_cast<
int>(idx % (n - 1));
5156 return {u, rem + (rem >= u)};
5161inline std::pair<
int,
int>
5162decode_graph_edge_index(
int n,
long long idx,
bool directed,
bool self_loops) {
5165 return {
int(idx / n),
int(idx % n)};
5166 return decode_directed_simple_edge(n, idx);
5169 return decode_undirected_loops_edge(n, idx);
5170 return decode_undirected_simple_edge(n, idx);
5176
5177
5178
5179
5180
5181
5182
5183
5185template <
typename VWeight,
typename EWeight>
5188 std::set<std::pair<
int,
int>> edges_;
5190 bool has_self_loops_;
5196 wgraph(
int n,
int m,
bool is_directed =
false,
bool has_self_loops =
false)
5197 : n_(n), m_(m), is_directed_(is_directed),
5198 has_self_loops_(has_self_loops) {
5199 tgen_ensure(n > 0,
"wgraph: number of vertices must be positive");
5205 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n_,
5206 "wgraph: vertices must be indexed in [0, n)");
5208 if (!is_directed_
and u > v)
5210 edges_.emplace(u, v);
5211 tgen_ensure(
static_cast<
int>(edges_.size()) <= m_,
5212 "wgraph: too many edges were added");
5226 std::vector<std::set<
int>> adj_;
5227 std::vector<std::pair<
int,
int>> edges_;
5229 bool print_1_based_;
5231 mutable bool adj_built_{
5234 std::optional<std::vector<VWeight>> vertex_weights_;
5235 std::optional<std::vector<EWeight>>
5241 value(
const std::vector<std::set<
int>> &adj,
bool is_directed =
false)
5242 : n_(
static_cast<
int>(adj.size())),
adj_(
adj),
5243 is_directed_(is_directed), print_1_based_(
false),
5244 print_nm_(
false), adj_built_(
true) {
5245 for (
int u = 0; u < n_; ++u)
5246 for (
auto v : adj[u]) {
5249 "wgraph: value: vertices must be indexed in [0, n)");
5253 if (is_directed_
or u <= v)
5254 edges_.emplace_back(u, v);
5262 value(
int n,
const std::vector<std::pair<
int,
int>> &edges = {},
5263 bool is_directed =
false)
5264 : n_(n),
edges_(), is_directed_(is_directed), print_1_based_(
false),
5265 print_nm_(
false), adj_built_(
false) {
5266 edges_.reserve(edges.size());
5267 std::unordered_set<uint64_t> seen;
5268 seen.reserve(edges.size() * 2 + 1);
5269 for (
auto [u, v] : edges) {
5271 0 <= std::min(u, v)
and std::max(u, v) < n,
5272 "wgraph: value: vertices must be indexed in [0, n)");
5273 if (!is_directed_
and u > v)
5275 uint64_t key = is_directed_ ? detail::directed_edge_key(u, v)
5276 : detail::undirected_edge_key(u, v);
5277 if (seen.insert(key).second)
5278 edges_.emplace_back(u, v);
5281 value(
int n,
const std::set<std::pair<
int,
int>> &edges,
5282 bool is_directed =
false)
5287 value(
int n,
const std::initializer_list<std::pair<
int,
int>> &edges,
5288 bool is_directed =
false)
5289 : value(n, std::vector<std::pair<
int,
int>>(edges), is_directed) {}
5294 :
value(t.n(), t.edges(),
false) {
5295 if (t.vertex_weights().has_value()) {
5296 vertex_weights_ = *t.vertex_weights();
5298 if (t.edge_weights().has_value()) {
5299 edge_weights_ = *t.edge_weights();
5305 template <
typename NewVWeight,
typename NewEWeight>
5306 typename wgraph<NewVWeight, NewEWeight>::value
5307 convert_weight_types()
const {
5309 !edge_weights_.has_value(),
5310 "wgraph: value: cannot convert weight type after "
5311 "assigning weights");
5314 typename wgraph<NewVWeight, NewEWeight>::value new_graph(
5315 adj_, is_directed_);
5316 new_graph.is_directed_ = is_directed_;
5317 new_graph.print_1_based_ = print_1_based_;
5318 new_graph.print_nm_ = print_nm_;
5323 int n()
const {
return n_; }
5326 int m()
const {
return static_cast<
int>(edges_.size()); }
5342 return vertex_weights_;
5347 return edge_weights_;
5352 template <
typename NewVWeight = VWeight>
5354 const std::vector<NewVWeight> &vertex_weights)
const {
5356 "wgraph: value: must give `n` vertex weights");
5358 auto new_graph = convert_weight_types<NewVWeight, EWeight>();
5359 new_graph.vertex_weights_ = vertex_weights;
5365 template <
typename NewEWeight = EWeight>
5369 "wgraph: value: must give `m` edge weights");
5371 auto new_graph = convert_weight_types<VWeight, NewEWeight>();
5372 new_graph.edge_weights_ = edge_weights;
5380 "wgraph: value: edge_weighted requires a graph with no "
5383 "wgraph: value: graph is already edge-weighted");
5385 edge_weights_ = std::vector<EWeight>();
5393 print_1_based_ =
true;
5414 std::vector<
int> new_label(
n());
5415 std::vector<
int> shuffled;
5416 for (
int i = 0; i <
n(); ++i) {
5417 if (indices.count(i))
5420 shuffled.push_back(i);
5422 std::vector<
int> targets = shuffled;
5423 tgen::shuffle(targets.begin(), targets.end());
5424 for (size_t k = 0; k < shuffled.size(); ++k)
5425 new_label[shuffled[k]] = targets[k];
5428 std::vector<std::set<
int>> new_adj(
n());
5429 for (
int u = 0; u < n(); ++u)
5430 for (
int v : adj_[u])
5431 new_adj[new_label[u]].insert(new_label[v]);
5435 for (
auto &[u, v] : edges_) {
5438 if (!is_directed_
and u > v)
5443 if (vertex_weights_.has_value()) {
5444 std::vector<VWeight> new_vw(
n());
5445 for (
int i = 0; i < n(); ++i)
5446 new_vw[new_label[i]] = (*vertex_weights_)[i];
5447 vertex_weights_ = new_vw;
5452 std::vector<
int> perm(edges_.size());
5453 std::iota(perm.begin(), perm.end(), 0);
5454 tgen::shuffle(perm.begin(), perm.end());
5456 std::vector<std::pair<
int,
int>> new_edges;
5457 std::optional<std::vector<EWeight>> new_ew;
5458 if (edge_weights_.has_value())
5459 new_ew = std::vector<EWeight>();
5460 for (
int i : perm) {
5461 new_edges.push_back(edges_[i]);
5462 if (new_ew.has_value())
5463 new_ew->push_back((*edge_weights_)[i]);
5467 if (new_ew.has_value())
5468 edge_weights_ = new_ew;
5481 new_vertex_weights = std::nullopt) {
5485 if (new_vertex_weights.has_value()) {
5487 "wgraph: value: cannot add weighted vertices to "
5488 "vertex-unweighted graph");
5490 static_cast<
int>(new_vertex_weights->size()) == k,
5491 "wgraph: value: number of vertex weights must be equal "
5492 "to number of added vertices");
5494 vertex_weights_->insert(vertex_weights_->end(),
5495 new_vertex_weights->begin(),
5496 new_vertex_weights->end());
5499 "wgraph: value: cannot add unweighted vertices to "
5500 "vertex-weighted graph");
5510 "wgraph: value: vertex ids must be valid");
5515 if (adj_[u].count(v))
5521 edges_.emplace_back(u, v);
5523 if (w.has_value()) {
5525 "wgraph: value: cannot add weighted edge to "
5526 "edge-unweighted graph");
5528 edge_weights_->push_back(*w);
5531 "wgraph: value: cannot add unweighted edge to "
5532 "edge-weighted graph");
5542 std::optional<EWeight> new_w = std::nullopt) {
5545 "wgraph: value: vertex ids must be valid");
5549 add_vertices(rhs.n(), rhs.vertex_weights());
5550 for (
int i = 0; i < rhs
.m(); ++i) {
5551 auto [u, v] = rhs.edges()[i];
5553 rhs.edge_weights().has_value()
5554 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5569 std::set<std::pair<
int,
int>> index_pairs) {
5572 "wgraph: value: graphs must have the same is_directed value");
5575 std::set<
int> idx_left, idx_right;
5576 std::vector<
int> right_id_to_left(rhs
.n(), -1);
5577 for (
auto [l, r] : index_pairs) {
5579 0 <= l
and l < n()
and 0 <= r
and r < rhs.n(),
5580 "wgraph: value: vertex indices to glue must be valid");
5581 tgen_ensure(idx_left.count(l) == 0
and idx_right.count(r) == 0,
5582 "wgraph: value: must not have repeated indices "
5583 "on the same side to glue");
5586 idx_right.insert(r);
5587 right_id_to_left[r] = l;
5591 std::vector<
int> new_right_id(rhs
.n(), -1);
5592 int intersection_lt = 0;
5593 std::optional<std::vector<VWeight>> rhs_vertex_weights;
5594 for (
int i = 0; i < rhs
.n(); ++i) {
5595 if (right_id_to_left[i] != -1) {
5598 new_right_id[i] = right_id_to_left[i];
5601 new_right_id[i] =
n() + i - intersection_lt;
5602 if (rhs.vertex_weights().has_value()) {
5603 if (!rhs_vertex_weights.has_value())
5604 rhs_vertex_weights = std::vector<VWeight>();
5605 rhs_vertex_weights->push_back(
5606 (*rhs.vertex_weights())[i]);
5612 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
5613 for (
int i = 0; i < rhs
.m(); ++i) {
5614 auto [u, v] = rhs.edges()[i];
5616 rhs.edge_weights().has_value()
5617 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5624 std::initializer_list<std::pair<
int,
int>> il) {
5625 return glue(rhs, std::set<std::pair<
int,
int>>(il));
5633 std::set<std::pair<
int,
int>> index_pairs;
5634 for (
auto i : indices)
5635 index_pairs.emplace(i, i);
5636 return glue(rhs, index_pairs);
5638 value &glue(
const value &rhs,
const std::initializer_list<
int> &il) {
5639 return glue(rhs, std::set<
int>(il));
5646 return glue(rhs, std::set<
int>());
5654 "wgraph: value: can choose at most `m` edges from graph");
5656 std::vector<std::pair<
int,
int>> new_edges;
5657 std::optional<std::vector<EWeight>> new_edge_weights;
5660 for (
int i = 0; i <
m(); ++i) {
5661 if (next(1, left--) <= num_edges) {
5662 new_edges.push_back(edges()[i]);
5663 if (edge_weights_.has_value()) {
5664 if (!new_edge_weights.has_value())
5665 new_edge_weights = std::vector<EWeight>();
5666 new_edge_weights->push_back((*edge_weights())[i]);
5673 edge_weights_ = new_edge_weights;
5674 rebuild_adj_from_edge_list();
5686 "wgraph: value: random_connected_subgraph is only for "
5687 "undirected graphs");
5690 "wgraph: value: can choose at most `m` edges from graph");
5694 std::vector<std::vector<std::pair<
int,
int>>> incident(
n());
5695 for (
int i = 0; i <
m(); ++i) {
5696 auto [u, v] = edges_[i];
5697 incident[u].emplace_back(v, i);
5698 incident[v].emplace_back(u, i);
5702 std::vector<
bool> vis(
n(),
false);
5703 std::vector<
int> queue;
5704 std::vector<
bool> in_tree(
m(),
false);
5705 int forest_edges = 0;
5707 for (
int start = 0; start <
n(); ++start) {
5711 queue.push_back(start);
5713 while (!queue.empty()) {
5715 tgen::next<
int>(0,
static_cast<
int>(queue.size()) - 1);
5717 std::swap(queue[i], queue.back());
5720 for (
auto [v, edge_idx] : incident[u]) {
5724 in_tree[edge_idx] =
true;
5731 num_edges >= forest_edges,
5732 "wgraph: value: random_connected_subgraph needs at least "
5733 "`n - c` edges, where `c` is the number of connected "
5737 std::vector<
int> tree_idx, rest_idx;
5738 for (
int i = 0; i <
m(); ++i) {
5740 tree_idx.push_back(i);
5742 rest_idx.push_back(i);
5745 tgen::shuffle(rest_idx.begin(), rest_idx.end());
5747 std::vector<
int> chosen_idx;
5748 chosen_idx.insert(chosen_idx.end(), tree_idx.begin(),
5750 chosen_idx.insert(chosen_idx.end(), rest_idx.begin(),
5751 rest_idx.begin() + num_edges - forest_edges);
5753 detail::tgen_ensure_against_bug(
5754 static_cast<
int>(chosen_idx.size()) == num_edges,
5755 "wgraph: value: chose a wrong number of edges");
5757 std::vector<std::pair<
int,
int>> new_edges;
5758 std::optional<std::vector<EWeight>> new_edge_weights;
5759 if (edge_weights_.has_value())
5760 new_edge_weights = std::vector<EWeight>();
5761 for (
int i : chosen_idx) {
5762 new_edges.push_back(edges_[i]);
5763 if (new_edge_weights.has_value())
5764 new_edge_weights->push_back((*edge_weights_)[i]);
5768 edge_weights_ = new_edge_weights;
5769 rebuild_adj_from_edge_list();
5777 "wgraph: value: cannot compute complement of "
5778 "edge-weighted graph");
5780 value complement = *
this;
5781 complement.ensure_adj_built();
5782 std::vector<std::pair<
int,
int>> compl_edges;
5783 for (
int i = 0; i < complement.n_; ++i) {
5784 std::set<
int> complement_adj;
5785 for (
int j = 0; j < complement.n_; ++j) {
5787 if (j == i
and complement.adj_[i].count(j))
5789 if (j != i
and !complement.adj_[i].count(j))
5793 complement_adj.insert(j);
5795 if (i <= j
or complement.is_directed_) {
5796 compl_edges.emplace_back(i, j);
5800 std::swap(complement.adj_[i], complement_adj);
5802 std::swap(complement.edges_, compl_edges);
5811 "wgraph: value: graphs must have the same "
5812 "is_directed value");
5815 rhs.vertex_weights().has_value(),
5816 "wgraph: value: cannot concatenate vertex-weighted "
5817 "wgraph to unweighted");
5819 rhs.edge_weights().has_value(),
5820 "wgraph: value: cannot concatenate edge-weighted "
5821 "wgraph to unweighted");
5823 value concat = *
this;
5824 concat.glue(rhs, std::set<std::pair<
int,
int>>());
5825 concat.print_1_based_ = print_1_based_ | rhs.print_1_based_;
5826 concat.print_nm_ = print_nm_ | rhs.print_nm_;
5833 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
5836 out << val.n() <<
" " << val.m() <<
'\n';
5839 if (val.vertex_weights()) {
5840 for (
int i = 0; i < val.n(); ++i) {
5843 out << (*val.vertex_weights())[i];
5849 for (
int i = 0; i < val.m(); ++i) {
5850 auto [u, v] = val.edges()[i];
5851 out << (u + val.print_1_based_) <<
" "
5852 << (v + val.print_1_based_);
5855 if (val.edge_weights().has_value())
5856 out <<
" " << (*val.edge_weights())[i];
5868 return std_type(n_, m(), adj_);
5876 std::vector<std::set<
int>> adj(n_ + 1);
5877 for (
int u = 0; u < n_; ++u)
5878 for (
int v : adj_[u])
5879 adj[u + 1].insert(v + 1);
5880 return std_type(n_,
m(), adj);
5887 void rebuild_adj_from_edge_list() {
5888 adj_.assign(n_, {});
5889 for (
auto [u, v] : edges_) {
5899 void ensure_adj_built()
const {
5902 const_cast<
value *>(
this)->rebuild_adj_from_edge_list();
5910 "wgraph: graphs must have the same is_directed value");
5912 for (
auto [u, v] : rhs.edges())
5922 detail::tgen_ensure_against_bug(
static_cast<
int>(edges_.size()) <= m_,
5923 "wgraph: too many edges were added");
5926 if (
static_cast<
int>(edges_.size()) == m_)
5927 return value(n_, edges_, is_directed_);
5932 if (
auto indexed = try_gen_by_edge_index())
5936 return gen_remaining_edges(
5937 std::vector<std::pair<
int,
int>>(edges_.begin(), edges_.end()));
5947 "wgraph: get_connected is only for undirected graphs");
5949 "wgraph: connected graph needs at least n - 1 edges");
5951 std::vector<std::pair<
int,
int>> edges;
5954 if (edges_.empty()) {
5956 std::vector<
int> prufer(n_ - 2);
5957 for (
int i = 0; i < n_ - 2; ++i)
5958 prufer[i] = next<
int>(0, n_ - 1);
5959 for (
auto [u, v] : detail::edges_from_prufer(std::move(prufer)))
5960 edges.emplace_back(u, v);
5963 edges.assign(edges_.begin(), edges_.end());
5965 std::vector<std::vector<
int>> adj(n_);
5966 for (
auto [u, v] : edges_) {
5967 adj[u].push_back(v);
5968 adj[v].push_back(u);
5971 std::vector<
int> comp_size;
5972 std::vector<std::vector<
int>> component_ids;
5973 std::vector<
bool> vis(n_,
false);
5976 for (
int i = 0; i < n_; ++i) {
5982 comp_size.push_back(0);
5983 component_ids.emplace_back();
5988 component_ids.back().push_back(u);
5989 for (
int v : adj[u]) {
5998 if (component_ids.size() > 1) {
5999 std::vector<
int> prufer_values = many_by_distribution(
6000 static_cast<
int>(component_ids.size()) - 2, comp_size);
6002 detail::edges_from_prufer(std::move(prufer_values)))
6003 edges.emplace_back(pick(component_ids[u]),
6004 pick(component_ids[v]));
6008 return gen_remaining_edges(std::move(edges));
6021 "wgraph: get_acyclic is only for directed graphs");
6023 if (edges_.empty()) {
6024 std::vector<
int> order(n_);
6025 std::iota(order.begin(), order.end(), 0);
6026 for (
int i = n_ - 1; i > 0; --i)
6027 std::swap(order[i], order[next(0, i)]);
6029 const long long max_pairs =
6030 static_cast<
long long>(n_) * (n_ - 1) / 2;
6032 "wgraph: not enough edges to generate");
6034 std::vector<std::pair<
int,
int>> edges;
6036 for (
long long idx : distinct_range<
long long>(0, max_pairs - 1)
6039 auto [i, j] = detail::decode_undirected_simple_edge(n_, idx);
6040 edges.emplace_back(order[i], order[j]);
6042 return value(n_, edges,
true);
6045 std::vector<std::vector<
int>> adj(n_);
6046 std::vector<
int> indeg(n_, 0);
6047 for (
auto [u, v] : edges_) {
6048 adj[u].push_back(v);
6052 std::vector<
int> available;
6053 for (
int i = 0; i < n_; ++i)
6055 available.push_back(i);
6058 std::vector<
int> order;
6059 while (!available.empty()) {
6060 int idx = next(0,
static_cast<
int>(available.size()) - 1);
6061 int u = available[idx];
6062 std::swap(available[idx], available.back());
6063 available.pop_back();
6066 for (
int v : adj[u])
6067 if (--indeg[v] == 0)
6068 available.push_back(v);
6072 "wgraph: preset edges contain a directed cycle");
6074 value acyclic(n_, edges_,
true);
6078 detail::tgen_ensure_against_bug(acyclic.m() <= m_,
6079 "wgraph: too many edges were added");
6081 if (acyclic.m() < m_) {
6082 std::vector<
int> order_pos(n_);
6083 for (
int i = 0; i < n_; ++i)
6084 order_pos[order[i]] = i;
6086 std::unordered_set<uint64_t> seen;
6087 seen.reserve(m_ * 2);
6088 for (
auto [u, v] : acyclic.edges())
6090 detail::undirected_edge_key(order_pos[u], order_pos[v]));
6092 const long long max_pairs =
6093 static_cast<
long long>(n_) * (n_ - 1) / 2;
6094 while (acyclic.m() < m_) {
6095 std::pair<
int,
int> edge;
6096 if (!detail::try_generate_distinct(seen, [&] {
6097 long long idx = next<
long long>(0, max_pairs - 1);
6098 edge = detail::decode_undirected_simple_edge(n_, idx);
6099 return detail::undirected_edge_key(edge.first,
6102 throw detail::error(
"wgraph: not enough edges to generate");
6103 acyclic.add_edge(order[edge.first], order[edge.second]);
6123 bool is_directed =
false) {
6126 "wgraph: skewed graph needs at least n - 1 edges to be connected");
6128 "wgraph: gen_skewed spread must be at least 2");
6130 value skewed(n, {}, is_directed);
6132 std::vector<
int> parent(n), depth(n, 0);
6134 for (
int i = 1; i < n; ++i) {
6135 int p = wnext<
int>(i, elongation);
6137 depth[i] = depth[p] + 1;
6138 skewed.add_edge(p, i);
6141 const int extra = m - (n - 1);
6148 constexpr int naive_ancestor_spread = 20;
6150 if (spread <= naive_ancestor_spread) {
6151 std::vector<std::pair<
int,
int>> candidates;
6152 candidates.reserve(n * spread);
6153 for (
int u = 0; u < n; ++u) {
6154 int max_k = std::min(spread, depth[u]);
6158 for (
int k = 2; k <= max_k; ++k) {
6160 candidates.emplace_back(v, u);
6164 tgen_ensure(extra <=
static_cast<
int>(candidates.size()),
6165 "wgraph: not enough edges to generate");
6167 for (
auto [v, u] : choose(candidates, extra))
6168 skewed.add_edge(v, u);
6172 while ((1 << lg) <= n)
6175 std::vector<std::vector<
int>> up(lg, std::vector<
int>(n));
6176 for (
int v = 0; v < n; ++v)
6177 up[0][v] = parent[v];
6178 for (
int j = 1; j < lg; ++j)
6179 for (
int v = 0; v < n; ++v)
6180 up[j][v] = up[j - 1][up[j - 1][v]];
6186 std::vector<
int> distribution = depth;
6187 for (
int &d : distribution)
6188 d = std::max(0, std::min(spread - 1, d - 1));
6190 distinct extra_edges([&]() -> std::pair<
int,
int> {
6191 int u =
static_cast<
int>(vertex_choice.next());
6192 int k = next(2, spread);
6194 for (
int j = 0; j < lg; ++j)
6200 while (skewed.m() < m) {
6201 std::pair<
int,
int> edge;
6203 edge = extra_edges.gen();
6204 }
catch (
const std::runtime_error &e) {
6205 if (std::string(e.what()) ==
6206 "tgen: distinct: no more distinct values")
6207 throw detail::error(
6208 "wgraph: not enough edges to generate");
6212 skewed.add_edge(edge.first, edge.second);
6226 tgen_ensure(m >= 0,
"wgraph: number of edges must be nonnegative");
6227 long long num_edges = 1LL * n1 * n2;
6229 "wgraph: bipartite graph has at most n1 * n2 edges");
6233 "wgraph: connected bipartite graph needs at least n1 + n2 - 1 "
6238 std::vector<std::pair<
int,
int>> edges;
6240 for (
long long idx : distinct_range<
long long>(0, num_edges - 1)
6243 edges.emplace_back(
static_cast<
int>(idx / n2),
6244 n1 +
static_cast<
int>(idx % n2));
6245 return value(n1 + n2, std::move(edges),
false);
6248 std::unordered_set<uint64_t> used_edges;
6249 used_edges.reserve(m * 2);
6250 std::vector<std::pair<
int,
int>> edges;
6253 auto pack_edge = [](
int u,
int v) -> uint64_t {
6256 return (
static_cast<uint64_t>(u) << 32) |
static_cast<uint32_t>(v);
6260 if (n1 > 0
and n2 > 0) {
6261 std::vector<
int> left = {next(0, n1 - 1)};
6262 std::vector<
int> right = {next(n1, n1 + n2 - 1)};
6263 std::vector<
int> remaining;
6266 remaining.reserve(n1 + n2 - 2);
6268 for (
int u = 0; u < n1; ++u)
6270 remaining.push_back(u);
6271 for (
int v = n1; v < n1 + n2; ++v)
6273 remaining.push_back(v);
6274 shuffle(remaining.begin(), remaining.end());
6276 auto add_tree_edge = [&](
int u,
int v) {
6277 used_edges.insert(pack_edge(u, v));
6278 edges.emplace_back(u, v);
6280 add_tree_edge(left[0], right[0]);
6282 for (
int vertex : remaining) {
6284 add_tree_edge(vertex, pick(right));
6285 left.push_back(vertex);
6287 add_tree_edge(pick(left), vertex);
6288 right.push_back(vertex);
6291 detail::tgen_ensure_against_bug(
6292 used_edges.size() == size_t(n1 + n2 - 1),
6293 "wgraph: invalid bipartite spanning tree size");
6297 while (edges.size() < size_t(m)) {
6298 int u = next(0, n1 - 1);
6299 int v = next(n1, n1 + n2 - 1);
6300 if (used_edges.insert(pack_edge(u, v)).second)
6301 edges.emplace_back(u, v);
6304 return value(n1 + n2, std::move(edges),
false);
6313 bool has_self_loops =
false) {
6314 tgen_ensure(n > 0,
"wgraph: number of vertices must be positive");
6315 tgen_ensure(p >= 0
and p <= 1,
"wgraph: probability must be in [0, 1]");
6317 long long max_edges =
6318 detail::max_graph_edges(n, is_directed, has_self_loops);
6324 for (
long long i = 0; i < max_edges; ++i)
6325 if (next<
double>(0.0, 1.0) < p)
6329 "wgraph: too many edges to generate");
6330 return wgraph(n,
static_cast<
int>(m), is_directed, has_self_loops)
6340 std::optional<
value> try_gen_by_edge_index()
const {
6341 if (!edges_.empty())
6342 return std::nullopt;
6344 long long max_edges =
6345 detail::max_graph_edges(n_, is_directed_, has_self_loops_);
6347 throw detail::error(
"wgraph: not enough edges to generate");
6348 if (max_edges <= 0
or 2LL * m_ <= max_edges)
6349 return std::nullopt;
6351 std::vector<std::pair<
int,
int>> edges;
6353 for (
long long idx :
6354 distinct_range<
long long>(0, max_edges - 1).gen_list(m_).to_std())
6355 edges.push_back(detail::decode_graph_edge_index(
6356 n_, idx, is_directed_, has_self_loops_));
6358 return value(n_, edges, is_directed_);
6364 value gen_remaining_edges(std::vector<std::pair<
int,
int>> edges)
const {
6365 detail::tgen_ensure_against_bug(
static_cast<
int>(edges.size()) <= m_,
6366 "wgraph: too many edges were added");
6368 if (
static_cast<
int>(edges.size()) == m_)
6369 return value(n_, edges, is_directed_);
6373 std::unordered_set<uint64_t> seen;
6374 seen.reserve(m_ * 2);
6375 for (
auto [u, v] : edges) {
6376 if (!is_directed_
and u > v)
6378 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)
6379 : detail::undirected_edge_key(u, v));
6382 while (
static_cast<
int>(edges.size()) < m_) {
6383 std::pair<
int,
int> edge;
6384 if (!detail::try_generate_distinct(seen, [&] {
6385 edge = detail::get_random_graph_edge(n_, is_directed_,
6387 if (!is_directed_
and edge.first > edge.second)
6388 std::swap(edge.first, edge.second);
6389 return is_directed_ ? detail::directed_edge_key(edge.first,
6391 : detail::undirected_edge_key(
6392 edge.first, edge.second);
6394 throw detail::error(
"wgraph: not enough edges to generate");
6395 edges.emplace_back(edge);
6398 return value(n_, edges, is_directed_);
6404template <
typename VWeight,
typename EWeight>
6406 const typename wgraph<VWeight, EWeight>::value &g)
6407 : n_(g.n()),
adj_(
g.
n()), print_1_based_(
false), print_n_(
false),
6409 tgen_ensure(g.n() > 0,
"wtree: value: graph must have at least one vertex");
6411 "wtree: value: graph must be undirected to form a tree");
6413 if (g.vertex_weights().has_value())
6414 vertex_weights_ = *g.vertex_weights();
6415 if (g.edge_weights().has_value())
6416 edge_weights_ = std::vector<EWeight>();
6421 std::vector<
int> order(g.m());
6422 std::iota(order.begin(), order.end(), 0);
6423 tgen::shuffle(order.begin(), order.end());
6425 std::vector<std::pair<
int,
int>> tree_edges;
6426 tree_edges.reserve(n_ - 1);
6428 for (
int i : order) {
6429 auto [u, v] = g.edges()[i];
6430 if (!dsu_.unite(u, v))
6435 tree_edges.emplace_back(u, v);
6438 if (edge_weights_.has_value())
6439 edge_weights_->push_back((*g.edge_weights())[i]);
6440 if (
static_cast<
int>(tree_edges.size()) == n_ - 1)
6444 tgen_ensure(
static_cast<
int>(tree_edges.size()) == n_ - 1,
6445 "wtree: value: graph must be connected to form a tree");
6447 edges_ = std::move(tree_edges);
6451
6452
6464
6465
6469inline graph::
value K(
int n) {
return graph(n, n * (n - 1) / 2).gen(); }
6476 graph g(n, n - 1, is_directed);
6477 for (
int i = 0; i + 1 < n; ++i)
6478 g.add_edge(i, i + 1);
6487 tgen_ensure(n >= 3,
"graph: cycle size must be at least 3");
6489 graph g(n, n, is_directed);
6490 for (
int i = 0; i < n; ++i)
6491 g.add_edge(i, (i + 1) % n);
6500 graph g(n1 + n2,
static_cast<
long long>(n1) * n2);
6501 for (
int i = 0; i < n1; ++i)
6502 for (
int j = 0; j < n2; ++j)
6503 g.add_edge(i, n1 + j);
6513
6514
6515
6516
6522 static_assert(std::is_arithmetic_v<T>,
6523 "point requires an arithmetic coordinate type");
6535 point(T x = 0, T y = 0) : x_(x), y_(y) {}
6538 T
x()
const {
return x_; }
6541 T
y()
const {
return y_; }
6545 static bool coord_eq(T a, T b) {
6546 if constexpr (std::is_integral_v<T>)
6548 constexpr T eps = T(1e-9);
6550 return d >= -eps
and d <= eps;
6555 if (!coord_eq(x_, p
.x()))
6562 return coord_eq(x_, p
.x())
and coord_eq(y_, p
.y());
6580 if constexpr (std::is_floating_point_v<T>)
6582 return product_t(x_) * p
.x() + product_t(y_) * p
.y();
6587 if constexpr (std::is_floating_point_v<T>)
6589 return product_t(x_) * p
.y() - product_t(y_) * p
.x();
6593 friend std::ostream &operator<<(std::ostream &out,
const point &p) {
6594 return out << p
.x() <<
' ' << p
.y();
6603 long long max_coord) {
6605 "geometry: random_points_general_position: n must be positive");
6607 "geometry: random_points_general_position: min_coord must be "
6608 "at most max_coord");
6610 static_cast<detail::i128>(max_coord) - min_coord <=
6611 std::numeric_limits<
long long>::max(),
6612 "geometry: random_points_general_position: coordinate range too large");
6613 uint64_t width = max_coord - min_coord;
6618 "geometry: random_points_general_position: coordinate range "
6627 std::vector<uint64_t> x_range(p - 1);
6628 std::iota(x_range.begin(), x_range.end(), 1);
6629 shuffle(x_range.begin(), x_range.end());
6630 std::vector<detail::i128> bx(n), by(n);
6631 for (
int i = 0; i < n; ++i) {
6632 uint64_t x = x_range[i];
6634 by[i] = math::modular_inverse(x, p);
6642 const int num_shears = 8;
6643 std::vector<detail::i128> lin_x = bx, lin_y = by;
6645 for (
int it = 0; it < num_shears; ++it) {
6646 bool vertical_shear = next(2) == 0;
6647 int shear_r = pick({-2, -1, 1, 2});
6649 for (
int i = 0; i < n; ++i) {
6651 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;
6653 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;
6662 detail::i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0],
6664 for (
int i = 1; i < n; ++i) {
6665 min_x = std::min(min_x, lin_x[i]);
6666 max_x = std::max(max_x, lin_x[i]);
6667 min_y = std::min(min_y, lin_y[i]);
6668 max_y = std::max(max_y, lin_y[i]);
6671 detail::i128 x_shift =
6673 next<uint64_t>(0,
static_cast<uint64_t>(width - (max_x - min_x)));
6674 detail::i128 y_shift =
6676 next<uint64_t>(0,
static_cast<uint64_t>(width - (max_y - min_y)));
6678 std::vector<point<
long long>> pts;
6679 for (
int i = 0; i < n; ++i)
6680 pts.emplace_back(
static_cast<
long long>(lin_x[i] + x_shift),
6681 static_cast<
long long>(lin_y[i] + y_shift));
6687using i128 = tgen::detail::i128;
6691inline i128 ccw(
const point<
long long> &a,
const point<
long long> &b,
6692 const point<
long long> &p) {
6693 return (
static_cast<i128>(b.x()) - a.x()) *
6694 (
static_cast<i128>(p.y()) - a.y()) -
6695 (
static_cast<i128>(b.y()) - a.y()) *
6696 (
static_cast<i128>(p.x()) - a.x());
6700inline i128 proj_on_ab(
const point<
long long> &P,
const point<
long long> &A,
6701 const point<
long long> &B) {
6702 return (P - A) * (B - A);
6708inline void conquer(std::vector<point<
long long>> &points,
int left,
6710 if (right - left <= 3)
6713 point<
long long> A = points[left], B = points[right - 1];
6716 bool all_collinear =
true;
6717 for (
int k = left + 1; k < right - 1; ++k) {
6718 if (ccw(A, B, points[k]) != 0) {
6719 all_collinear =
false;
6723 if (all_collinear) {
6724 std::sort(points.begin() + left, points.begin() + right,
6725 [&](
const point<
long long> &P,
const point<
long long> &Q) {
6726 return proj_on_ab(P, A, B) < proj_on_ab(Q, A, B);
6732 std::vector<
int> candidates;
6733 for (
int k = left + 1; k < right - 1; ++k) {
6734 if (ccw(A, B, points[k]) != 0)
6735 candidates.push_back(k);
6737 int ci = candidates[next(0,
static_cast<
int>(candidates.size()) - 1)];
6738 point<
long long> C = points[ci];
6740 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6741 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6742 bool a_on_positive = ccw(C, A, B) < 0;
6746 i128 proj_sum = proj_on_ab(A, A, B) + proj_on_ab(B, A, B);
6747 auto is_positive = [&](
const point<
long long> &P) ->
bool {
6748 i128 s = wa * ccw(C, A, P) + wb * ccw(C, B, P);
6753 return 2 * proj_on_ab(P, A, B) > proj_sum;
6758 if (ci != right - 2)
6759 std::swap(points[ci], points[right - 2]);
6764 if (is_positive(points[i]) == a_on_positive)
6766 else if (is_positive(points[j]) != a_on_positive)
6769 std::swap(points[i], points[j]);
6780 if (i == j
and is_positive(points[i]) == a_on_positive)
6782 std::swap(points[p], points[right - 2]);
6785 conquer(points, left, p + 1);
6787 conquer(points, p, right);
6794inline std::vector<
long long>
6795sample_sorted_distinct_in_range(
int k,
long long left,
long long right) {
6796 long long universe = right - left + 1;
6797 std::vector<
long long> res;
6802 constexpr long long pool_threshold = 8'000'000;
6803 constexpr long long pool_always_below = 500'000;
6805 if (universe <= pool_threshold
and
6806 (universe <= pool_always_below
or k >= universe / 4)) {
6807 size_t u = universe;
6809 std::vector<
long long> pool(u);
6810 std::iota(pool.begin(), pool.end(), left);
6811 size_t m = ks <= u / 2 ? ks : u - ks;
6812 for (size_t i = 0; i < m; ++i) {
6813 size_t j = next<size_t>(i, u - 1);
6814 std::swap(pool[i], pool[j]);
6817 res.assign(pool.begin(), pool.begin() + ks);
6818 std::sort(res.begin(), res.end());
6820 std::vector<
char> excluded(u, 0);
6821 for (size_t i = 0; i < m; ++i)
6822 excluded[pool[i] - left] = 1;
6823 for (
long long v = left; v <= right; ++v)
6824 if (!excluded[v - left])
6828 std::unordered_map<
long long,
long long> virtual_list;
6829 virtual_list.reserve(k * 2);
6830 for (
long long i = 0; i < k; ++i) {
6831 long long j = next<
long long>(i, universe - 1);
6832 long long vi = virtual_list.count(i) ? virtual_list[i] : i;
6833 long long vj = virtual_list.count(j) ? virtual_list[j] : j;
6834 virtual_list[j] = vi;
6835 virtual_list[i] = vj;
6836 res.push_back(virtual_list[i] + left);
6838 std::sort(res.begin(), res.end());
6845inline std::vector<
long long>
6846valtr_edge_components(
const std::vector<
long long> &sorted_coords) {
6847 int n =
static_cast<
int>(sorted_coords.size());
6848 std::vector<
long long> left, right;
6849 left.reserve(n / 2);
6850 right.reserve(n / 2);
6851 for (
int i = 1; i + 1 < n; ++i) {
6853 left.push_back(sorted_coords[i]);
6855 right.push_back(sorted_coords[i]);
6857 long long lo = sorted_coords.front(), hi = sorted_coords.back();
6858 std::vector<
long long> seq;
6861 for (
long long v : left)
6864 for (
auto it = right.rbegin(); it != right.rend(); ++it)
6867 std::vector<
long long> comps(n);
6868 for (
int i = 0; i < n; ++i)
6869 comps[i] = seq[i + 1] - seq[i];
6875inline std::vector<point<
long long>>
6876simplify_strict_boundary(std::vector<point<
long long>> points) {
6877 int n =
static_cast<
int>(points.size());
6881 std::vector<point<
long long>> strict_points;
6882 strict_points.reserve(n);
6883 for (
int i = 0; i < n; ++i) {
6884 if (ccw(points[(i + n - 1) % n], points[i], points[(i + 1) % n]) != 0)
6885 strict_points.push_back(points[i]);
6887 return strict_points;
6892inline std::vector<point<
long long>>
6893subsample_boundary(
const std::vector<point<
long long>> &points,
int k) {
6894 int n =
static_cast<
int>(points.size());
6898 std::vector<point<
long long>> sampled_points;
6899 sampled_points.reserve(k);
6900 for (
int i = 0; i < k; ++i)
6901 sampled_points.push_back(
6902 points[
static_cast<size_t>((
static_cast<i128>(i) * n) / k)]);
6903 return sampled_points;
6908inline void place_inside_box(std::vector<point<
long long>> &points,
6909 long long min_coord,
long long max_coord) {
6910 long long width = max_coord - min_coord + 1;
6912 i128 min_x = points[0].x(), max_x = points[0].x();
6913 i128 min_y = points[0].y(), max_y = points[0].y();
6914 for (
const point<
long long> &p : points) {
6915 min_x = std::min(min_x,
static_cast<i128>(p.x()));
6916 max_x = std::max(max_x,
static_cast<i128>(p.x()));
6917 min_y = std::min(min_y,
static_cast<i128>(p.y()));
6918 max_y = std::max(max_y,
static_cast<i128>(p.y()));
6921 i128 span_x = max_x - min_x;
6922 i128 span_y = max_y - min_y;
6926 next<
long long>(0, width - 1 -
static_cast<
long long>(span_x));
6929 next<
long long>(0, width - 1 -
static_cast<
long long>(span_y));
6931 for (point<
long long> &p : points)
6932 p = point<
long long>(
static_cast<
long long>(p.x() + shift_x),
6933 static_cast<
long long>(p.y() + shift_y));
6938inline void randomize_cyclic_shift(std::vector<point<
long long>> &points) {
6939 int rot = next(
static_cast<
int>(points.size()));
6941 std::rotate(points.begin(), points.begin() + rot, points.end());
6946inline std::vector<point<
long long>>
6947valtr_vertices(
int m,
const std::vector<
long long> &x_comp,
6948 std::vector<
long long> y_comp) {
6949 shuffle(y_comp.begin(), y_comp.end());
6951 std::vector<point<
long long>> edges(m);
6953 auto upper = [](
const point<
long long> &p) {
6954 return p.y() > 0
or (p.y() == 0
and p.x() > 0);
6956 for (
int i = 0; i < m; ++i)
6957 edges[i] =
point<
long long>(x_comp[i], y_comp[i]);
6959 std::sort(edges.begin(), edges.end(),
6960 [&upper](
const point<
long long> &a,
const point<
long long> &b) {
6961 bool au = upper(a), bu = upper(b);
6967 return (a * a) < (b * b);
6971 i128 cur_x = 0, cur_y = 0;
6972 std::vector<i128> px(m), py(m);
6973 for (
int i = 0; i < m; ++i) {
6976 cur_x += edges[i].x();
6977 cur_y += edges[i].y();
6979 tgen::detail::tgen_ensure_against_bug(
6980 cur_x == 0
and cur_y == 0,
6981 "geometry: random_convex_polygon: walk did not close");
6983 i128 min_x = px[0], min_y = py[0];
6984 for (
int i = 1; i < m; ++i) {
6985 min_x = std::min(min_x, px[i]);
6986 min_y = std::min(min_y, py[i]);
6990 std::vector<point<
long long>> points;
6992 for (
int i = 0; i < m; ++i)
6993 points.emplace_back(px[i] - min_x, py[i] - min_y);
7006 bool strict =
false) {
7008 "geometry: random_convex_polygon: n must be at least 3");
7010 "geometry: random_convex_polygon: min_coord must be at most "
7012 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7013 std::numeric_limits<
long long>::max(),
7014 "geometry: random_convex_polygon: coordinate range too large");
7015 long long width = max_coord - min_coord + 1;
7018 "geometry: random_convex_polygon: coordinate range too small for n");
7026 int extra = width <= n ? 0
7027 :
static_cast<
int>(std::min<
long long>(
7028 std::max(100, n / 1000), width - n));
7029 num_coords = n + extra;
7034 const int max_attempts = strict ? 32 : 1;
7035 for (
int i = 0; i < max_attempts; ++i) {
7037 std::vector<
long long> x_sorted =
7038 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
7039 std::vector<
long long> y_sorted =
7040 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
7041 std::vector<
long long> x_comp = detail::valtr_edge_components(x_sorted);
7042 std::vector<
long long> y_comp = detail::valtr_edge_components(y_sorted);
7044 std::vector<point<
long long>> points =
7045 detail::valtr_vertices(num_coords, x_comp, std::move(y_comp));
7048 std::vector<point<
long long>> simplified =
7049 detail::simplify_strict_boundary(std::move(points));
7051 if (
static_cast<
int>(simplified.size()) < n)
7054 points = detail::subsample_boundary(simplified, n);
7057 detail::place_inside_box(points, min_coord, max_coord);
7058 detail::randomize_cyclic_shift(points);
7063 throw tgen::detail::error(
7064 "geometry: random_convex_polygon: generation failed: coordinate "
7065 "range too small for n");
7073 const std::vector<point<
long long>> &points) {
7074 int n =
static_cast<
int>(points.size());
7076 "geometry: random_simple_polygon_through_points: need at "
7080 std::set<point<
long long>>(points.begin(), points.end()).size()) ==
7082 "geometry: random_simple_polygon_through_points: points must "
7085 int idx_a = 0, idx_b = 0;
7086 for (
int i = 1; i < n; ++i) {
7087 if (points[i] < points[idx_a])
7089 if (points[idx_b] < points[i])
7092 point<
long long> A = points[idx_a], B = points[idx_b];
7094 bool all_collinear =
true;
7095 for (
int i = 0; i < n; ++i) {
7096 if (i == idx_a
or i == idx_b)
7098 if (detail::ccw(A, B, points[i]) != 0) {
7099 all_collinear =
false;
7104 "geometry: random_simple_polygon_through_points: all points "
7105 "are collinear; no simple polygon exists");
7110 int negative_count = 0;
7111 for (
int i = 0; i < n; ++i) {
7112 if (i == idx_a
or i == idx_b)
7114 if (detail::ccw(A, B, points[i]) < 0)
7118 std::vector<point<
long long>> chain;
7121 for (
int i = 0; i < n; ++i) {
7122 if (i == idx_a
or i == idx_b)
7124 detail::i128 side = detail::ccw(A, B, points[i]);
7125 if (side < 0
or (side == 0
and negative_count == 0)) {
7126 chain.push_back(points[i]);
7131 for (
int i = 0; i < n; ++i) {
7132 if (i == idx_a
or i == idx_b)
7134 detail::i128 side = detail::ccw(A, B, points[i]);
7135 if (side > 0
or (side == 0
and negative_count != 0))
7136 chain.push_back(points[i]);
7140 int n1 = 2 + left_count;
7142 detail::conquer(chain, 0, n1);
7144 detail::conquer(chain, n1 - 1,
static_cast<
int>(chain.size()));
7148 std::vector<point<
long long>> poly;
7149 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);
7150 poly.insert(poly.end(), chain.begin() + n1, chain.end());
7158inline std::vector<point<
long long>>
7159random_distinct_points_in_box(
int n,
long long min_coord,
long long max_coord) {
7160 long long width = max_coord - min_coord;
7161 i128 side_128 = width + 1;
7162 i128 universe = side_128 * side_128;
7163 tgen_ensure(universe <= std::numeric_limits<
long long>::max(),
7164 "geometry: random_simple_polygon: coordinate range too large");
7165 long long side =
static_cast<
long long>(side_128);
7167 "geometry: random_simple_polygon: coordinate range too small "
7168 "for n distinct points");
7171 auto decode = [&](
long long key) ->
point<
long long> {
7172 return point<
long long>(min_coord + key / side, min_coord + key % side);
7178 std::vector<
long long> keys =
7179 distinct_range<
long long>(0,
static_cast<
long long>(universe - 1))
7183 std::vector<point<
long long>> points;
7185 for (
long long key : keys)
7186 points.push_back(decode(key));
7189 for (
int i = 2; i < n; ++i) {
7190 if (ccw(points[0], points[1], points[i]) != 0)
7198struct ortho_poly_edge {
7208inline bool ortho_axis_collinear(
const point<
long long> &a,
7209 const point<
long long> &b,
7210 const point<
long long> &c) {
7211 return (a.x() == b.x()
and b.x() == c.x())
or
7212 (a.y() == b.y()
and b.y() == c.y());
7217inline ortho_poly_edge
7218ortho_analyze_edge(
const std::vector<point<
long long>> &poly,
int i) {
7219 int m =
static_cast<
int>(poly.size());
7220 point<
long long> a = poly[i], b = poly[(i + 1) % m];
7221 ortho_poly_edge e{};
7222 if (a.y() == b.y()) {
7225 e.lo = std::min(a.x(), b.x());
7226 e.hi = std::max(a.x(), b.x());
7228 e.out_y = a.x() < b.x() ? -1 : 1;
7231 e.lo = std::min(a.y(), b.y());
7232 e.hi = std::max(a.y(), b.y());
7233 e.out_x = a.y() < b.y() ? 1 : -1;
7235 e.len = e.hi - e.lo;
7242inline bool ortho_open_seg_cross(
const point<
long long> &a,
7243 const point<
long long> &b,
7244 const point<
long long> &c,
7245 const point<
long long> &d) {
7246 if (a.y() == b.y()
and c.y() == d.y()) {
7249 long long lo1 = std::min(a.x(), b.x()), hi1 = std::max(a.x(), b.x());
7250 long long lo2 = std::min(c.x(), d.x()), hi2 = std::max(c.x(), d.x());
7251 return lo1 < hi2
and lo2 < hi1;
7253 if (a.x() == b.x()
and c.x() == d.x()) {
7256 long long lo1 = std::min(a.y(), b.y()), hi1 = std::max(a.y(), b.y());
7257 long long lo2 = std::min(c.y(), d.y()), hi2 = std::max(c.y(), d.y());
7258 return lo1 < hi2
and lo2 < hi1;
7260 if (a.y() == b.y()
and c.x() == d.x()) {
7261 long long hx = a.y(), vx = c.x();
7262 long long hlo = std::min(a.x(), b.x()), hhi = std::max(a.x(), b.x());
7263 long long vlo = std::min(c.y(), d.y()), vhi = std::max(c.y(), d.y());
7264 return hlo < vx
and vx < hhi
and vlo < hx
and hx < vhi;
7266 if (a.x() == b.x()
and c.y() == d.y()) {
7267 long long vx = a.x(), hy = c.y();
7268 long long vlo = std::min(a.y(), b.y()), vhi = std::max(a.y(), b.y());
7269 long long hlo = std::min(c.x(), d.x()), hhi = std::max(c.x(), d.x());
7270 return vlo < hy
and hy < vhi
and hlo < vx
and vx < hhi;
7277inline bool ortho_point_inside(
const std::vector<point<
long long>> &poly,
7278 point<
long long> p) {
7279 int m =
static_cast<
int>(poly.size());
7280 bool inside =
false;
7281 for (
int i = 0, j = m - 1; i < m; j = i++) {
7282 point<
long long> a = poly[i], b = poly[j];
7283 if ((a.y() > p.y()) != (b.y() > p.y())) {
7284 i128 x_cross = i128(b.x() - a.x()) * (p.y() - a.y()) -
7285 i128(p.x() - a.x()) * (b.y() - a.y());
7286 if ((a.y() < b.y()) ? x_cross > 0 : x_cross < 0)
7295inline bool ortho_point_strictly_interior(
point<
long long> p,
7297 point<
long long> b) {
7298 if (a.y() == b.y()) {
7301 long long lo = std::min(a.x(), b.x()), hi = std::max(a.x(), b.x());
7302 return lo < p.x()
and p.x() < hi;
7304 if (a.x() == b.x()) {
7307 long long lo = std::min(a.y(), b.y()), hi = std::max(a.y(), b.y());
7308 return lo < p.y()
and p.y() < hi;
7315inline bool ortho_point_on_segment(
point<
long long> p,
point<
long long> a,
7316 point<
long long> b) {
7317 return p == a
or p == b
or ortho_point_strictly_interior(p, a, b);
7325inline bool ortho_bump_valid(
const std::vector<point<
long long>> &poly,
7327 const std::vector<point<
long long>> &add,
7328 int edge_i,
bool inward) {
7329 int m =
static_cast<
int>(poly.size());
7331 for (point<
long long> v : add)
7332 for (point<
long long> q : poly)
7338 for (point<
long long> v : add) {
7339 for (
int j = 0; j < m; ++j) {
7340 point<
long long> c = poly[j], d = poly[(j + 1) % m];
7342 if (ortho_point_on_segment(v, c, d)
and
7343 !ortho_point_on_segment(v, A, B))
7345 }
else if (ortho_point_strictly_interior(v, c, d)) {
7351 auto seg_ok = [&](
point<
long long> s0,
point<
long long> s1) {
7352 for (
int j = 0; j < m; ++j) {
7355 point<
long long> c = poly[j], d = poly[(j + 1) % m];
7356 if (ortho_open_seg_cross(s0, s1, c, d))
7359 for (
int k = 0; k < m; ++k) {
7360 point<
long long> q = poly[k];
7361 if (q == s0
or q == s1
or q == A
or q == B)
7363 if (ortho_point_strictly_interior(q, s0, s1))
7369 point<
long long> prev = A;
7370 for (point<
long long> v : add) {
7371 if (!seg_ok(prev, v))
7375 if (!seg_ok(prev, B))
7379 for (point<
long long> v : add)
7380 if (!ortho_point_inside(poly, v))
7390inline bool ortho_bump_edge(std::vector<point<
long long>> &poly,
int edge_i,
7391 const ortho_poly_edge &e,
long long lo,
7392 long long hi,
long long depth,
bool inward,
7393 size_t max_vertices) {
7394 int m =
static_cast<
int>(poly.size());
7395 point<
long long> A = poly[edge_i], B = poly[(edge_i + 1) % m];
7397 int step_x = inward ? -e.out_x : e.out_x;
7398 int step_y = inward ? -e.out_y : e.out_y;
7400 std::vector<point<
long long>> add;
7402 long long y = e.fixed, y2 = y + step_y * depth;
7403 if (A.x() < B.x()) {
7405 add.emplace_back(lo, y);
7406 add.emplace_back(lo, y2);
7407 add.emplace_back(hi, y2);
7409 add.emplace_back(hi, y);
7412 add.emplace_back(hi, y);
7413 add.emplace_back(hi, y2);
7414 add.emplace_back(lo, y2);
7416 add.emplace_back(lo, y);
7419 long long x = e.fixed, x2 = x + step_x * depth;
7420 if (A.y() < B.y()) {
7422 add.emplace_back(x, lo);
7423 add.emplace_back(x2, lo);
7424 add.emplace_back(x2, hi);
7426 add.emplace_back(x, hi);
7429 add.emplace_back(x, hi);
7430 add.emplace_back(x2, hi);
7431 add.emplace_back(x2, lo);
7433 add.emplace_back(x, lo);
7436 if (poly.size() > max_vertices
or add.size() > max_vertices - poly.size())
7438 if (!ortho_bump_valid(poly, A, B, add, edge_i, inward))
7441 poly.insert(poly.begin() + edge_i + 1, add.begin(), add.end());
7448inline int ortho_pick_poly_edge(
const std::vector<point<
long long>> &poly,
7449 std::vector<
int> &last_used,
int &time_stamp) {
7450 int m =
static_cast<
int>(poly.size());
7451 if (last_used.size() !=
static_cast<size_t>(m)) {
7452 last_used.assign(m, 0);
7455 std::vector<
long long> weights(m);
7456 long long total = 0;
7457 for (
int i = 0; i < m; ++i) {
7458 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7459 weights[i] = e.len * (4 + std::min(time_stamp - last_used[i], 8));
7460 total += weights[i];
7462 long long pick = next<
long long>(0, total - 1);
7463 for (
int i = 0; i < m; ++i) {
7466 last_used[i] = ++time_stamp;
7470 last_used[m - 1] = ++time_stamp;
7477ortho_try_bump(std::vector<point<
long long>> &poly,
int n,
7478 std::vector<
int> &last_used,
int &time_stamp,
7479 bool outward_only =
false,
7480 size_t max_vertices = std::numeric_limits<size_t>::max()) {
7481 if (poly.size() < 3)
7484 int ei = ortho_pick_poly_edge(poly, last_used, time_stamp);
7485 ortho_poly_edge e = ortho_analyze_edge(poly, ei);
7492 long long span = next<
long long>(2, e.len);
7493 long long lo = next<
long long>(e.lo, e.hi - span);
7497 long long max_depth =
7498 std::clamp(
static_cast<
long long>(std::sqrt(n) / 2 + 2), 2LL, 12LL);
7500 next(10) == 0 ? next<
long long>(std::max(2LL, max_depth / 2), max_depth)
7501 : next<
long long>(1, std::max(2LL, max_depth / 3));
7503 bool inward = !outward_only
and next(4) == 0;
7504 return ortho_bump_edge(poly, ei, e, lo, lo + span, depth, inward,
7510inline std::vector<point<
long long>>
7511ortho_simplify_collinear(std::vector<point<
long long>> poly) {
7512 int n =
static_cast<
int>(poly.size());
7515 std::vector<point<
long long>> out;
7517 for (
int i = 0; i < n; ++i) {
7518 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7520 out.push_back(poly[i]);
7522 return out.size() >= 3 ? out : poly;
7527inline bool ortho_remove_one_collinear(std::vector<point<
long long>> &poly) {
7528 int n =
static_cast<
int>(poly.size());
7531 for (
int i = 0; i < n; ++i) {
7532 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7535 poly.erase(poly.begin() + i);
7544inline void ortho_fill_collinear(std::vector<point<
long long>> &poly,
7546 int need = target -
static_cast<
int>(poly.size());
7550 std::vector<point<
long long>> out;
7551 int m =
static_cast<
int>(poly.size());
7552 out.reserve(poly.size() + need);
7554 for (
int i = 0; i < m; ++i) {
7555 point<
long long> a = poly[i], b = poly[(i + 1) % m];
7560 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7561 long long cap = e.len - 1;
7566 long long take = std::min<
long long>(need, cap);
7567 bool forward = e.horiz ? a.x() < b.x() : a.y() < b.y();
7568 for (
long long k = 0; k < take; ++k) {
7569 long long off = (k + 1) * (cap + 1) / (take + 1);
7570 long long coord = forward ? e.lo + off : e.hi - off;
7572 out.push_back({coord, e.fixed});
7574 out.push_back({e.fixed, coord});
7576 need -=
static_cast<
int>(take);
7588inline void ortho_fill_corrugation(std::vector<point<
long long>> &poly,
7590 size_t n_sz = poly.size();
7594 size_t extra_left = target - n_sz;
7596 std::vector<point<
long long>> out;
7597 out.reserve(target);
7598 int n =
static_cast<
int>(poly.size());
7600 for (
int i = 0; i < n; ++i) {
7601 point<
long long> a = poly[i], b = poly[(i + 1) % n];
7607 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7611 long long dir = (e.horiz ? a.x() < b.x() : a.y() < b.y()) ? 1 : -1;
7612 long long start = e.horiz ? a.x() : a.y();
7613 long long end = e.horiz ? b.x() : b.y();
7615 for (
long long pos = start + 2 * dir;
7616 extra_left >= 4
and (pos - end) * dir <= -3; pos += 2 * dir) {
7618 long long y2 = e.fixed + e.out_y;
7619 out.push_back({pos, e.fixed});
7620 out.push_back({pos, y2});
7621 out.push_back({pos + dir, y2});
7622 out.push_back({pos + dir, e.fixed});
7624 long long x2 = e.fixed + e.out_x;
7625 out.push_back({e.fixed, pos});
7626 out.push_back({x2, pos});
7627 out.push_back({x2, pos + dir});
7628 out.push_back({e.fixed, pos + dir});
7639inline std::vector<point<
long long>> build_orthogonal_polygon(
int n,
7641 bool scale_up = n > 1000;
7643 long long side = std::max(3LL,
static_cast<
long long>(std::sqrt(n)));
7645 side = std::clamp(
static_cast<
long long>(2 * std::sqrt(std::sqrt(n))),
7647 std::vector<point<
long long>> poly = {
7648 {0, 0}, {side, 0}, {side, side}, {0, side}};
7650 int target_ops = scale_up ? std::max(1,
static_cast<
int>(4 * side - 4) / 2)
7651 : std::max(1, (n - 4) / 2);
7654 target_ops = std::min(
7656 400 +
static_cast<
int>(4 * std::sqrt(
static_cast<
double>(side))));
7658 int failure_limit = std::min(target_ops * 8, 2000);
7660 std::vector<
int> last_used;
7661 int time_stamp = 0, consecutive_failures = 0;
7662 size_t max_vertices =
7663 scale_up ? std::numeric_limits<size_t>::max() :
static_cast<size_t>(n);
7664 for (
int ops = 0; ops < target_ops;) {
7665 if (!scale_up
and poly.size() + 2 >
static_cast<size_t>(n))
7668 if (ortho_try_bump(poly, n, last_used, time_stamp, scale_up,
7671 consecutive_failures = 0;
7672 }
else if (++consecutive_failures >= failure_limit) {
7677 poly = ortho_simplify_collinear(std::move(poly));
7680 while (poly.size() >
static_cast<size_t>(n)
and
7681 ortho_remove_one_collinear(poly))
7683 long long upscale = std::max(4LL, ((n + 3) / 4 + side - 1) / side);
7684 for (point<
long long> &p : poly)
7685 p = {p.x() * upscale, p.y() * upscale};
7687 ortho_fill_corrugation(poly, n);
7689 ortho_fill_collinear(poly, n);
7691 ortho_fill_collinear(poly, n);
7707 bool strict =
false) {
7709 "geometry: random_simple_polygon: n must be at least 3");
7711 "geometry: random_simple_polygon: min_coord must be at most "
7713 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord <=
7714 std::numeric_limits<
long long>::max(),
7715 "geometry: random_simple_polygon: coordinate range too large");
7717 std::vector<point<
long long>> points =
7718 strict ? random_points_general_position(n, min_coord, max_coord)
7719 : detail::random_distinct_points_in_box(n, min_coord, max_coord);
7720 return random_simple_polygon_through_points(points);
7729 bool strict =
false) {
7731 "geometry: random_orthogonal_polygon: n must be at least 4");
7733 "geometry: random_orthogonal_polygon: min_coord must be at "
7735 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7736 std::numeric_limits<
long long>::max(),
7737 "geometry: random_orthogonal_polygon: coordinate range too "
7739 long long width = max_coord - min_coord + 1;
7741 "geometry: random_orthogonal_polygon: coordinate range too "
7744 long long min_side = std::max(3LL,
static_cast<
long long>(std::sqrt(n)));
7746 min_side = std::max<
long long>(min_side, (n + 3) / 4);
7748 "geometry: random_orthogonal_polygon: coordinate range too "
7751 for (
int attempt = 0; attempt < 8; ++attempt) {
7752 std::vector<point<
long long>> poly =
7753 detail::build_orthogonal_polygon(n, strict);
7755 if (!strict
and poly.size() !=
static_cast<size_t>(n))
7758 detail::i128 min_x = poly[0].x(), max_x = poly[0].x();
7759 detail::i128 min_y = poly[0].y(), max_y = poly[0].y();
7760 for (point<
long long> p : poly) {
7761 min_x = std::min(min_x, detail::i128(p.x()));
7762 max_x = std::max(max_x, detail::i128(p.x()));
7763 min_y = std::min(min_y, detail::i128(p.y()));
7764 max_y = std::max(max_y, detail::i128(p.y()));
7766 if (max_x - min_x >= width
or max_y - min_y >= width)
7769 detail::place_inside_box(poly, min_coord, max_coord);
7770 detail::randomize_cyclic_shift(poly);
7774 throw tgen::detail::error(
7775 "geometry: random_orthogonal_polygon: generation failed");
7781
7782
7783
7784
7790using namespace tgen::detail;
7794inline int hash_string(
const std::string &s,
int base,
int mod) {
7797 h = (h * base + c -
'a' + 1) % mod;
7798 return static_cast<
int>(h);
7802inline int estimate_length(
int alphabet_size,
int mod) {
7804 double base_len = 2.5 * std::log(std::sqrt(mod));
7805 double scale = std::log(alphabet_size) / std::log(2.0);
7806 double adjusted = base_len / std::max(1.0, scale * 0.7);
7808 return static_cast<
int>(std::ceil(adjusted));
7813inline std::pair<std::string, std::string>
7814birthday_attack(
const std::vector<std::string> &alphabet,
int base,
int mod) {
7816 "birthday_attack: base must be in (0, mod)");
7817 std::map<uint64_t, std::vector<
int>> seen;
7818 int length = estimate_length(
static_cast<
int>(alphabet.size()), mod);
7821 std::vector<
int> seq(length);
7825 for (
int i = 0; i < length; ++i) {
7826 seq[i] = next<
int>(0,
static_cast<
int>(alphabet.size()) - 1);
7827 s += alphabet[seq[i]];
7830 int h = hash_string(s, base, mod);
7832 auto it = seen.find(h);
7833 if (it != seen.end()
and it->second != seq) {
7836 for (
int x : it->second)
7851inline std::set<
long long> std_hash_multipliers() {
7852 std::set<
long long> multipliers = {85229};
7855 bool codeforces_gcc_case =
true;
7856 if (cpp.version_ != 0
and cpp.version_ != 17)
7857 codeforces_gcc_case =
false;
7858 if (compiler.kind_ != compiler_kind::unknown
and
7859 compiler.kind_ != compiler_kind::gcc)
7860 codeforces_gcc_case =
false;
7861 if (compiler.major_ > 7)
7862 codeforces_gcc_case =
false;
7864 if (codeforces_gcc_case)
7865 multipliers.insert(107897);
7876 std::string str =
"a";
7878 while (
static_cast<
int>(str.size()) < n) {
7879 int prev_size =
static_cast<
int>(str.size());
7881 for (
int j = 0; j < prev_size
and static_cast<
int>(str.size()) < n; ++j)
7894 for (
int i = 0; i < size; ++i) {
7895 a +=
static_cast<
char>(
'a' + math::detail::popcount(i) % 2);
7896 b +=
static_cast<
char>(
'a' + (
'b' - a[i]));
7905 int base,
int mod) {
7907 "hack: polynomial_hash: alphabet size must be greater "
7910 "hack: polynomial_hash: base must be in (0, mod)");
7912 std::vector<std::string> alphabet(alphabet_size);
7913 for (
int i = 0; i < alphabet_size; ++i)
7914 alphabet[i] = std::string(1,
static_cast<
char>(
'a' + i));
7915 std::iota(alphabet.begin(), alphabet.end(),
'a');
7916 return detail::birthday_attack(alphabet, base, mod);
7923inline std::pair<std::string, std::string>
7925 std::vector<
int> mods) {
7927 "hack: polynomial_hash: bases and mods must have the same "
7930 "hack: polynomial_hash: must have at least one (base, mod) "
7933 "hack: polynomial_hash: multi-hash hack only supported "
7934 "for up to 2 (base, mod) pairs");
7936 std::vector<std::string> alphabet(alphabet_size);
7937 for (
int i = 0; i < alphabet_size; ++i)
7938 alphabet[i] = std::string(1,
static_cast<
char>(
'a' + i));
7939 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);
7940 if (bases.size() == 1)
7942 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);
7948 tgen_ensure(size > 0,
"hack: std_unordered: size must be positive");
7949 std::set<
long long> multipliers = detail::std_hash_multipliers();
7951 std::set<
long long>::iterator it = multipliers.begin();
7953 std::vector<
long long> list;
7954 while (
static_cast<
int>(list.size()) < size) {
7955 list.push_back(mult * (*it));
7957 if (it == multipliers.end()) {
7958 it = multipliers.begin();
7970 std::set<std::pair<
int,
int>> queries;
7973 int sq =
static_cast<
int>(std::sqrt(n));
7974 for (
int i = 0; i < sq; ++i) {
7975 for (
int j = i; j < sq; ++j) {
7976 if (i * sq < n
and j * sq < n)
7977 queries.emplace(i * sq, j * sq);
7982 for (
int i = 0; i < n; ++i)
7983 if (queries.size() < size_t(q)) {
7984 queries.emplace(0, i);
7985 queries.emplace(i, i);
7986 queries.emplace(i, n - 1);
7989 std::vector<std::pair<
int,
int>> pool(queries.begin(), queries.end());
7990 while (pool.size() < size_t(q)) {
7991 int l = next(0, n - 1);
7992 pool.emplace_back(l, next(l, n - 1));
7995 return choose(shuffled(pool), q);
8003 std::vector<std::string> list;
8004 int k = 0, left = size;
8006 int cur_size = std::min(left, k + 1);
8009 char right_char = cur_size == k + 1 ?
'b' :
'c';
8010 list.push_back(std::string(cur_size - 1,
'a') + right_char);
8014 return tgen::shuffled(list);
8026 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");
8028 egraph<
int>::value g(n, {},
true);
8030 g.add_edge(0, 1, 1);
8031 g.add_edge(0, 2, 1);
8032 for (
int i = 1; i + 2 < n; i += 2) {
8033 g.add_edge(i, i + 2, 1);
8035 g.add_edge(i, i + 3, 1);
8037 g.add_edge(i + 1, i + 2, 1);
8039 g.add_edge(i + 1, i + 3, 1);
8042 return g.shuffle_except({0});
8055 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");
8058 egraph<
int>::value g(n, {},
true);
8060 for (
int i = 1; i < mid; ++i)
8061 g.add_edge(0, i, i);
8062 for (
int i = 1; i < mid; ++i)
8063 g.add_edge(i, mid, 2 * (mid - i) - 1);
8064 for (
int i = mid + 1; i < n; ++i)
8065 g.add_edge(mid, i, 1);
8067 return g.shuffle_except({0});
8078 tgen_ensure(n >= 2,
"hack: spfa: n must be at least 2");
8079 tgen_ensure(n % 2 == 0,
"hack: spfa: n must be even");
8081 egraph<
int>::value g(n, {},
true);
8084 const int k = n / 2;
8085 for (
int i = 0; i + 1 < k; ++i)
8086 g.add_edge(i, i + 1, 1);
8087 for (
int i = 0; i + 1 < k; ++i)
8088 g.add_edge(k + i, k + i + 1, 0);
8089 for (
int i = 0; i < k; ++i)
8090 g.add_edge(i, k + i, 0);
8091 for (
int i = 0; i + 1 < k; ++i)
8092 g.add_edge(k + i, i + 1, 1);
8094 return g.shuffle_except({0});
8102 tgen_ensure(k >= 1,
"hack: dinitz_worst_case: k must be at least 1");
8103 tgen_ensure(l >= 1,
"hack: dinitz_worst_case: l must be at least 1");
8105 const int p1 = 2 * l - 1;
8106 const int p2 = 2 * l;
8107 const int q1 = 2 * l + 1;
8108 const int q2 = 2 * l + 2;
8109 const int n = 4 * l + 2 * k + 2;
8111 const int flow_cap = k * k * l;
8112 const int layer_cap = k * k;
8114 auto a = [&](
int i) {
return 2 * l + 3 + 2 * i; };
8115 auto b = [&](
int i) {
return 2 * l + 4 + 2 * i; };
8116 auto t = [&](
int i) {
return 4 * l + 2 * k + 1 - i; };
8118 egraph<
int>::value g(n, {},
true);
8121 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
8122 g.add_edge(i, i + 1, flow_cap);
8123 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
8124 g.add_edge(t(i + 1), t(i), flow_cap);
8126 for (
int i = 0; i < 2 * l - 1; i += 2) {
8127 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);
8128 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);
8131 for (
int i = 0; i < k; ++i) {
8132 g.add_edge(p1, a(i), flow_cap);
8133 g.add_edge(p2, b(i), flow_cap);
8134 g.add_edge(a(i), q2, flow_cap);
8135 g.add_edge(b(i), q1, flow_cap);
8138 for (
int i = 0; i < k; ++i)
8139 for (
int j = 0; j < k; ++j)
8140 g.add_edge(a(i), b(j), 1);
8149 static_assert(std::is_same_v<T,
int>
or std::is_same_v<T,
long long>,
8150 "hack: mt19937_xor_hash: T must be int or long long");
8152 constexpr std::size_t deg = 19937;
8154 std::bitset<deg + 1> a, b, c;
8155 b[deg] = c[deg] = 1;
8156 std::size_t l = 0, shift = 1;
8158 std::mt19937_64 rng64;
8159 for (std::size_t n = 0; n < deg * 2; ++n) {
8161 if constexpr (std::is_same_v<T,
int>)
8162 a[deg] = rng32() & 1;
8164 a[deg] = rng64() & 1;
8166 if ((c & a).count() % 2 == 0) {
8171 std::bitset<deg + 1> oc = c;
8182 std::vector<
bool> mask(deg + 1);
8183 for (std::size_t i = 0; i <= deg; ++i)
8195 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},
8196 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},
8204inline std::vector<
int> segment_tree_beats_worst_case_block(
int k) {
8206 "hack: segment_tree_beats_worst_case: k must be at least 1");
8208 std::vector<
int> a(k + 1), b(k + 1);
8209 std::vector<std::vector<
int>> vf(k + 1), vg(k + 1);
8215 for (
int i = 2; i <= k; ++i) {
8216 b[i] = b[i - 1] + a[i - 1];
8217 a[i] = b[i] + a[i - 1];
8218 for (
int x : vf[i - 1])
8219 vf[i].push_back(x + a[i] + b[i]);
8220 vf[i].push_back(a[i]);
8221 for (
int x : vg[i - 1])
8222 vf[i].push_back(x + a[i]);
8225 for (
int x : vg[i - 1])
8236segment_tree_beats_append_round(std::vector<std::vector<
int>> &updates,
8237 int block_len,
int an,
int bn,
int n,
8239 const int off = (round * an) % block_len;
8240 const int add_off = (off + block_len - bn) % block_len;
8241 for (
int k = 0; k < block_len; ++k) {
8242 const int s = k * block_len * block_len;
8243 const int sub_end = off + an;
8244 if (sub_end <= block_len)
8245 updates.push_back({1, s + off, s + sub_end, bn});
8247 updates.push_back({1, s + off, s + block_len, bn});
8248 updates.push_back({1, s, s + (sub_end - block_len), bn});
8250 const int add_end = add_off + bn;
8251 if (add_end <= block_len)
8252 updates.push_back({0, s + add_off, s + add_end, an});
8254 updates.push_back({0, s + add_off, s + block_len, an});
8255 updates.push_back({0, s, s + (add_end - block_len), an});
8258 updates.push_back({2, 0, n, an});
8259 for (
int k = 0; k < block_len; ++k) {
8260 const int s = k * block_len * block_len;
8261 updates.push_back({3, s + (off + an - 1) % block_len, 0});
8269inline std::pair<std::vector<
int>, std::vector<std::vector<
int>>>
8270segment_tree_beats_worst_case(
int k,
int q) {
8272 "hack: segment_tree_beats_worst_case: k must be at least 1");
8273 tgen_ensure(k <= 7,
"hack: segment_tree_beats_worst_case: k too large");
8275 "hack: segment_tree_beats_worst_case: q must be positive");
8277 const auto &fib = math::fibonacci();
8278 const int block_len =
static_cast<
int>(fib[k * 2 + 1]);
8279 const int an =
static_cast<
int>(fib[k * 2]);
8280 const int bn =
static_cast<
int>(fib[k * 2 - 1]);
8282 const int len = block_len;
8283 const int total = len * len * len;
8285 std::vector<
int> block = detail::segment_tree_beats_worst_case_block(k);
8286 std::vector<
int> arr(total, 0);
8287 for (
int x = 0; x < block_len; ++x) {
8288 const int s = x * len * len;
8289 for (
int i = 0; i < block_len; ++i)
8290 arr[s + i] = block[i];
8293 std::vector<std::vector<
int>> updates;
8295 const int n = total;
8296 for (
int round = 0; updates.size() <
static_cast<std::size_t>(q); ++round) {
8297 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,
8299 if (updates.size() >
static_cast<std::size_t>(q))
8302 return {arr, updates};
8310inline tree::value binary_heap_tree(
int n) {
8311 std::vector<std::pair<
int,
int>> edges;
8312 for (
int i = 0; i < n; ++i) {
8314 edges.emplace_back(i, 2 * i + 1);
8316 edges.emplace_back(i, 2 * i + 2);
8318 return tree::value(n, edges);
8323inline void heap_subtree_leaves(
int n,
int u, std::vector<
int> &out) {
8324 if (2 * u + 1 >= n) {
8328 heap_subtree_leaves(n, 2 * u + 1, out);
8330 heap_subtree_leaves(n, 2 * u + 2, out);
8337inline std::vector<std::pair<
int,
int>> tree_path_worst_queries(
int n,
int q) {
8338 std::vector<
int> left, right;
8340 heap_subtree_leaves(n, 1, left);
8342 heap_subtree_leaves(n, 2, right);
8344 std::vector<std::pair<
int,
int>> queries;
8345 for (
int i = 0; i < q; ++i)
8346 queries.emplace_back(pick(left), pick(right));
8352inline int reverse_bits(
int x,
int bits) {
8354 for (
int i = 0; i < bits; ++i) {
8355 r = (r << 1) | (x & 1);
8365inline std::vector<
int> lct_worst_access(
int n,
int q) {
8366 int first_leaf = n / 2;
8367 int m = n - first_leaf;
8370 while ((1u << bits) <
static_cast<
unsigned>(m))
8373 std::vector<
int> order;
8374 int span = 1 << bits;
8375 for (
int i = 0; i < span; ++i) {
8376 int r = reverse_bits(i, bits);
8378 order.push_back(first_leaf + r);
8381 std::vector<
int> access;
8382 for (
int i = 0; i < q; ++i)
8383 access.push_back(order[i % m]);
8392inline std::pair<tree::value, std::vector<std::pair<
int,
int>>>
8393centroid_decomposition_worst_case(
int n,
int q) {
8396 "hack: centroid_decomposition_worst_case: n must be at least 3");
8399 "hack: centroid_decomposition_worst_case: q must be at least 1");
8401 return {detail::binary_heap_tree(n), detail::tree_path_worst_queries(n, q)};
8407inline std::pair<tree::value, std::vector<std::pair<
int,
int>>>
8408heavy_light_decomposition_worst_case(
int n,
int q) {
8411 "hack: heavy_light_decomposition_worst_case: n must be at least "
8415 "hack: heavy_light_decomposition_worst_case: q must be at least 1");
8417 return {detail::binary_heap_tree(n), detail::tree_path_worst_queries(n, q)};
8422inline std::pair<tree::value, std::vector<
int>>
8423link_cut_tree_worst_case(
int n,
int q) {
8424 tgen_ensure(n >= 2,
"hack: link_cut_tree_worst_case: n must be at least 2");
8425 tgen_ensure(q >= 1,
"hack: link_cut_tree_worst_case: q must be at least 1");
8427 return {detail::binary_heap_tree(n), detail::lct_worst_access(n, q)};
8433
8434
8435
8436
8445 "misc: parenthesis: size must be a positive even number");
8449 int open = 0, close = 0;
8451 for (
int i = 0; i < size; ++i) {
8457 if (open == close) {
8463 long long a = k - open, b = k - close, h = open - close;
8468 long long num = a * (h + 2);
8469 long long den = (a + b) * (h + 1);
8471 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.