← comparison
tgen 1.1.0
Loading...
Searching...
No Matches
tgen.h
1/*
2 * Copyright (c) 2026 Bruno Monteiro
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include <algorithm>
26#include <bitset>
27#include <cstdint>
28#include <functional>
29#include <initializer_list>
30#include <iomanip>
31#include <iostream>
32#include <limits>
33#include <map>
34#include <optional>
35#include <queue>
36#include <random>
37#include <set>
38#include <sstream>
39#include <stdexcept>
40#include <string>
41#include <sys/types.h>
42#include <type_traits>
43#include <unordered_map>
44#include <unordered_set>
45#include <utility>
46#include <vector>
47
48namespace tgen {
49
50/**************************
51 * *
52 * GENERAL OPERATIONS *
53 * *
54 **************************/
55
56namespace detail {
57
58// Type aliases.
59using u128 = unsigned __int128;
60using i128 = __int128;
61
62/*
63 * Error handling.
64 */
65
66inline void throw_assertion_error(const std::string &condition,
67 const std::string &msg, const char *file,
68 int line) {
69 throw std::runtime_error("tgen: " + msg + " (assertion `" + condition +
70 "` failed at " + file + ":" +
71 std::to_string(line) + ")");
72}
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));
77}
78inline std::runtime_error error(const std::string &msg) {
79 return std::runtime_error("tgen: " + msg);
80}
81inline std::runtime_error contradiction_error(const std::string &type,
82 const std::string &msg = "") {
83 // Tried to generate a contradictory type.
84 std::string error_msg =
85 type + ": invalid " + type + " (contradictory restrictions)";
86 if (!msg.empty())
87 error_msg += ": " + msg;
88 return error(error_msg);
89}
90inline std::runtime_error
91complex_restrictions_error(const std::string &type,
92 const std::string &msg = "") {
93 // Tried to generate a type with too many distinct restrictions.
94 std::string error_msg =
95 type + ": cannot represent " + type + " (complex restrictions)";
96 if (!msg.empty())
97 error_msg += ": " + msg;
98 return error(error_msg);
99}
100inline void tgen_ensure_against_bug(bool cond, const std::string &msg = "") {
101 if (!cond) {
102 std::string error_msg;
103 if (!msg.empty())
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);
107 }
108}
109
110// Ensures condition is true, with a clear error message on failure.
111#define tgen_ensure(cond, ...)
112 if (!(cond))
113 tgen::detail::throw_assertion_error(#cond, ##__VA_ARGS__, __FILE__,
114 __LINE__)
115
116// Registering checks.
117inline bool registered = false;
118inline void ensure_registered() {
119 tgen_ensure(registered,
120 "tgen was not registered! You should call "
121 "tgen::register_gen(argc, argv) before running tgen functions");
122}
123
124// Template magic to detect types at compile time.
125
126// Detects containers != std::string.
127template <typename T, typename = void> struct is_container : std::false_type {};
128template <typename T>
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>()))>>
133 : std::true_type {};
134// Exclude all basic_string variants
135template <typename Char, typename Traits, typename Alloc>
136struct is_container<std::basic_string<Char, Traits, Alloc>> : std::false_type {
137};
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 {};
147
148// Detects std::pair.
149template <typename T> struct is_pair : std::false_type {};
150template <typename A, typename B>
151struct is_pair<std::pair<A, B>> : std::true_type {};
152// Detects std::tuple.
153template <typename T> struct is_tuple : std::false_type {};
154template <typename... Ts>
155struct is_tuple<std::tuple<Ts...>> : std::true_type {};
156// Detects scalar (printed atomically).
157template <typename T>
158struct is_scalar
159 : std::bool_constant<!is_container<T>::value and !is_tuple<T>::value and
160 !is_pair<T>::value> {};
161// Detects complex container.
162template <typename T>
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> {
167};
168// Detects complex std::pair.
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> {};
173// Detects complex std::tuple.
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 ...)> {};
178
179// Used to return false at compile time only if evaluated.
180template <typename> inline constexpr bool dependent_false_v = false;
181
182/*
183 * Properties of custom types.
184 */
185
186// If type is sequential (list-like).
187using is_sequential_tag = void;
188
189// Detects associative containers.
190template <typename T, typename = void>
191struct is_associative_container : std::false_type {};
192template <typename T>
193struct is_associative_container<
194 T, std::void_t<typename T::key_type, typename T::key_compare>>
195 : std::true_type {};
196
197// Detects sequential generator values.
198template <typename T, typename = void>
199struct is_sequential : std::false_type {};
200template <typename T>
201struct is_sequential<
202 T, std::void_t<typename std::decay_t<T>::tgen_is_sequential_tag>>
203 : std::true_type {};
204
205/*
206 * Unique rng to use.
207 */
208
209// The single rng to be used by the library.
210inline std::mt19937 rng;
211
212/*
213 * Printing.
214 */
215
216// Print view struct for printing either a container or a sequential generator
217// element.
218template <typename T,
219 bool IsCont = detail::is_container<std::decay_t<T>>::value>
220struct print_cols_view;
221
222// Container.
223template <typename T> struct print_cols_view<T, true> {
224 const T &value;
225 decltype(std::begin(std::declval<const T &>())) it;
226
227 print_cols_view(const T &v) : value(v), it(v.begin()) {}
228
229 std::size_t size() const { return value.size(); }
230 decltype(auto) get(std::size_t) const { return *it; }
231 void advance() { ++it; }
232};
233
234// Sequential generator element.
235template <typename T> struct print_cols_view<T, false> {
236 const T &value;
237
238 print_cols_view(const T &v) : value(v) {}
239
240 std::size_t size() const { return value.size(); }
241 decltype(auto) get(std::size_t i) const { return value[i]; }
242 void advance() {}
243};
244
245/*
246 * Distinct generation.
247 */
248
249// Rejection cap is multiplier * |seen|; with one value left, falsely reporting
250// exhaustion has probability about e^{-84} < 10^{-36}.
251constexpr int distinct_attempt_multiplier = 84;
252
253// One rejection-sampling step for distinct generation.
254// O(T * log k + log^2 k) amortized expected time per call when generating k
255// distinct values and next() runs in O(T).
256template <typename Seen, typename Fn>
257auto try_generate_distinct(Seen &seen, Fn &&next, bool insert = true)
258 -> std::optional<std::invoke_result_t<Fn &>> {
259 using T = std::invoke_result_t<Fn &>;
260 size_t attempts =
261 distinct_attempt_multiplier * std::max<size_t>(1, seen.size());
262 for (size_t i = 0; i < attempts; ++i) {
263 T val = next();
264 if (insert) {
265 if (seen.insert(val).second)
266 return val;
267 } else if (seen.count(val) == 0)
268 return val;
269 }
270 return std::nullopt;
271}
272
273} // namespace detail
274
275/*
276 * Compiler configuration (see set_compiler).
277 */
278
279// Kinds of compilers.
280enum class compiler_kind { gcc, clang, unknown };
281
282// Compiler identity and version.
284 compiler_kind kind_;
285 int major_;
286 int minor_;
287
288 compiler_value(compiler_kind kind = compiler_kind::unknown, int major = 0,
289 int minor = 0)
290 : kind_(kind), major_(major), minor_(minor) {}
291};
292
293namespace detail {
294
295// Global C++ version value (0 means unknown).
296struct cpp_value {
297 int version_;
298
299 cpp_value(std::optional<int> version = std::nullopt)
300 : version_(version ? *version : 0) {
301 if (version) {
302 tgen_ensure(*version == 17 or *version == 20 or *version == 23,
303 "unsupported C++ version (use 17, 20, 23)");
304 }
305 }
306};
307
308inline cpp_value cpp;
309inline compiler_value compiler;
310
311} // namespace detail
312
313/*
314 * Base classes.
315 */
316
317// Needed for return type of some functions.
318template <typename T> struct list;
319
320// Generates distinct values of a function.
321template <typename Func, typename... Args> struct distinct {
322 Func func_;
323 std::tuple<Args...> args_;
324 using T = std::invoke_result_t<Func &, Args &...>;
325 std::set<T> seen_;
326
327 distinct(Func func, Args... args)
328 : func_(std::move(func)), args_(std::move(args)...) {}
329
330 // Generates a distinct value (i.e., one not returned before).
331 //
332 // Assume gen() produces a uniformly random value in O(T) time.
333 // Since duplicates are rejected, the expected number of trials over
334 // k successful generations is:
335 //
336 // sum_{i=1}^k k / i = O(k log k)
337 //
338 // (coupon collector argument).
339 //
340 // Each trial additionally performs O(log k) work to check/store
341 // previously generated values, yielding a total time of
342 // O((T + log k) * k log k).
343 //
344 // Thus, the amortized expected time per call is
345 // O(T * log k + log^2 k).
346 //
347 // With extremely small probability (< 1e-18), the algorithm may
348 // incorrectly report that no more distinct values exist.
349 auto gen() {
350 auto val = generate_distinct(true);
351 if (val)
352 return *val;
353
354 throw detail::error("distinct: no more distinct values");
355 }
356 template <typename U> auto gen(std::initializer_list<U> il) {
357 return gen(std::vector<U>(il));
358 }
359
360 // Generates a list of distinct values.
361 auto gen_list(int size) {
362 std::vector<T> res;
363 for (int i = 0; i < size; ++i)
364 res.push_back(gen());
365
366 return typename list<T>::value(res);
367 }
368
369 // Checks if there are no more distinct values.
370 // With extremely small probability (< 1e-18), the algorithm may
371 // incorrectly report that there are no more distinct values.
372 bool empty() { return generate_distinct(false) == std::nullopt; }
373
374 // Generates all distinct values.
375 auto gen_all() {
376 std::vector<T> res;
377 while (true) {
378 auto val = generate_distinct(true);
379 if (val)
380 res.push_back(*val);
381 else
382 break;
383 }
384 return typename list<T>::value(res);
385 }
386
387 // Nice error for `out << distinct`.
388 friend std::ostream &operator<<(std::ostream &out, const distinct &) {
389 static_assert(
390 detail::dependent_false_v<distinct>,
391 "distinct: cannot print a distinct generator. Maybe you forgot to "
392 "call `gen()`?");
393 return out;
394 }
395
396 private:
397 // Generates distinct value and inserts it if `insert` is true.
398 // Returns the value if found, otherwise returns std::nullopt.
399 auto generate_distinct(bool insert) {
400 return detail::try_generate_distinct(
401 seen_, [&] { return std::apply(func_, args_); }, insert);
402 }
403};
404template <typename Func, typename... Args>
405distinct(Func, Args...) -> distinct<Func, Args...>;
406
407// Base struct for generators.
408template <typename Gen> struct gen_base {
409 const Gen &self() const { return *static_cast<const Gen *>(this); }
410
411 template <typename... Args> auto gen_list(int size, Args &&...args) const {
412 std::vector<typename Gen::value> res;
413
414 for (int i = 0; i < size; ++i)
415 res.push_back(static_cast<const Gen *>(this)->gen(
416 std::forward<Args>(args)...));
417
418 return typename list<typename Gen::value>::value(res);
419 }
420
421 // Calls the generator until predicate is true.
422 template <typename Pred, typename... Args>
423 auto gen_until(Pred predicate, int max_tries, Args &&...args) const {
424 for (int i = 0; i < max_tries; ++i) {
425 typename Gen::value val = static_cast<const Gen *>(this)->gen(
426 std::forward<Args>(args)...);
427
428 if (predicate(val))
429 return val;
430 }
431
432 throw detail::error("could not generate value matching predicate");
433 }
434 template <typename Pred, typename T, typename... Args>
435 auto gen_until(Pred predicate, int max_tries, std::initializer_list<T> il,
436 Args &&...args) const {
437 return gen_until(predicate, max_tries, std::vector<T>(il),
438 std::forward<Args>(args)...);
439 }
440
441 // Distinct for generator.
442 template <typename... Args> auto distinct(Args &&...args) const {
443 return tgen::distinct(
444 [self = self()](auto &&...inner_args) mutable -> decltype(auto) {
445 return self.gen(
446 std::forward<decltype(inner_args)>(inner_args)...);
447 },
448 std::forward<Args>(args)...);
449 }
450 template <typename T, typename... Args>
451 auto distinct(std::initializer_list<T> il, Args &&...args) const {
452 return distinct(std::vector<T>(il), std::forward<Args>(args)...);
453 }
454
455 // Nice error for `out << generator`.
456 friend std::ostream &operator<<(std::ostream &out, const gen_base &) {
457 static_assert(detail::dependent_false_v<gen_base>,
458 "gen_base: cannot print a generator. Maybe you forgot to "
459 "call `gen()`?");
460 return out;
461 }
462};
463
464// Base class for generator values.
465template <typename Val> struct gen_value_base {
466 const Val &self() const { return *static_cast<const Val *>(this); }
467
468 bool operator<(const Val &rhs) const {
469 return self().to_std() < rhs.to_std();
470 }
471};
472
473namespace detail {
474
475// Detects generator values.
476template <typename T>
477struct is_generator_value
478 : std::is_base_of<gen_value_base<std::decay_t<T>>, std::decay_t<T>> {};
479
480} // namespace detail
481
482/*
483 * Easier printing.
484 */
485
486// Struct to print standard types to std::ostream;
487struct print {
488 std::string s_;
489
490 template <typename T> print(const T &val, char sep = ' ') {
491 std::ostringstream oss;
492 write(oss, val, sep);
493 s_ = oss.str();
494 }
495 template <typename T>
496 print(const std::initializer_list<T> &il, char sep = ' ') {
497 std::ostringstream oss;
498 write(oss, std::vector<T>(il), sep);
499 s_ = oss.str();
500 }
501 template <typename T>
502 print(const std::initializer_list<std::initializer_list<T>> &il,
503 char sep = ' ') {
504 std::ostringstream oss;
505 std::vector<std::vector<T>> mat;
506 for (const auto &i : il)
507 mat.push_back(i);
508 write(oss, mat, sep);
509 s_ = oss.str();
510 }
511
512 template <typename T> void write(std::ostream &os, const T &val, char sep) {
513 if constexpr (detail::is_pair<T>::value) {
514 if constexpr (detail::is_pair_multiline<T>::value) {
515 write(os, val.first, sep);
516 os << '\n';
517 write(os, val.second, sep);
518 } else {
519 // Use space for inner separator.
520 write(os, val.first, ' ');
521 os << sep;
522 write(os, val.second, ' ');
523 }
524 } else if constexpr (detail::is_tuple<T>::value)
525 write_tuple(os, val, sep);
526 else if constexpr (detail::is_container<T>::value)
527 write_container(os, val, sep);
528 else if constexpr (std::is_same_v<T, detail::i128> or
529 std::is_same_v<T, detail::u128>)
530 write_128_number(os, val);
531 else
532 os << val;
533 }
534
535 // Writes 128 bit number.
536 template <typename T> void write_128_number(std::ostream &os, T num) {
537 static const long long BASE = 1e18;
538
539 if (num < 0) {
540 os << '-';
541 num = -num;
542 }
543
544 if (num >= BASE) {
545 write_128_number(os, num / BASE);
546 os << std::setw(18) << std::setfill('0')
547 << static_cast<long long>(num % BASE);
548 } else
549 os << static_cast<long long>(num);
550 }
551 // Writes container, checking separator.
552 template <typename C>
553 void write_container(std::ostream &os, const C &container, char sep) {
554 bool first = true;
555
556 for (const auto &e : container) {
557 if (!first)
558 os << (detail::is_container_multiline<C>::value ? '\n' : sep);
559 first = false;
560 write(os, e, detail::is_container_multiline<C>::value ? sep : ' ');
561 }
562 }
563
564 // Writes tuple, checking separator.
565 template <typename Tuple, size_t... I>
566 void write_tuple_impl(std::ostream &os, const Tuple &tp, char sep,
567 std::index_sequence<I...>) {
568 bool first = true;
569 ((os << (first ? (first = false, "")
570 : (detail::is_tuple_multiline<Tuple>::value
571 ? "\n"
572 : std::string(1, sep))),
573 write(os, std::get<I>(tp),
574 detail::is_tuple_multiline<Tuple>::value ? sep : ' ')),
575 ...);
576 }
577 template <typename T>
578 void write_tuple(std::ostream &os, const T &tp, char sep) {
579 write_tuple_impl(os, tp, sep,
580 std::make_index_sequence<std::tuple_size<T>::value>{});
581 }
582
583 friend std::ostream &operator<<(std::ostream &out, const print &pr) {
584 return out << pr.s_;
585 }
586};
587
588// Prints in a new line.
589struct println : print {
590 template <typename T>
591 println(const T &val, char sep = ' ') : print(val, sep) {}
592 template <typename T>
593 println(const std::initializer_list<T> &il, char sep = ' ')
594 : print(il, sep) {}
595 template <typename T>
596 println(const std::initializer_list<std::initializer_list<T>> &il,
597 char sep = ' ')
598 : print(il, sep) {}
599
600 friend std::ostream &operator<<(std::ostream &out, const println &pr) {
601 return out << pr.s_ << '\n';
602 }
603};
604
605// Prints container / sequential generator value on its own column.
606// Example:
607// A = {1, 2, 3}, B = {4, 2, 5}
608// print_each(A, B) will print:
609// "1 4
610// 2 2
611// 3 5
612//",
613// that is, it prints the end of the line for all lines.
614template <typename... Args> struct print_cols {
615 std::string s_;
616
617 print_cols(const Args &...args) {
618 static_assert(
619 ((detail::is_container<std::decay_t<Args>>::value or
620 detail::is_sequential<std::decay_t<Args>>::value) and
621 ...),
622 "print_cols: arguments must be containers or sequential generator "
623 "values");
624 std::ostringstream oss;
625 write(oss, args...);
626 s_ = oss.str();
627 }
628
629 void write(std::ostream &os, const Args &...args) {
630 auto views = std::apply(
631 [](const Args &...inner_args) {
632 return std::make_tuple(
633 detail::print_cols_view<decltype(inner_args)>{
634 inner_args}...);
635 },
636 std::forward_as_tuple(args...));
637
638 const std::size_t n = std::get<0>(views).size();
639
640 auto check = [&](const auto &v) {
641 tgen_ensure(v.size() == n, "print_cols: sizes should be the same");
642 };
643 std::apply([&](const auto &...v) { (check(v), ...); }, views);
644
645 for (std::size_t i = 0; i < n; ++i) {
646 bool first = true;
647
648 std::apply(
649 [&](const auto &...v) {
650 ((os << (first ? "" : " ") << print(v.get(i)),
651 first = false),
652 ...);
653 },
654 views);
655
656 os << '\n';
657
658 std::apply([](auto &...v) { (v.advance(), ...); }, views);
659 }
660 }
661
662 friend std::ostream &operator<<(std::ostream &out, const print_cols &pr) {
663 return out << pr.s_;
664 }
665};
666
667/*
668 * Global random operations.
669 */
670
671namespace detail {
672
673// libstdc++ accepts std::uniform_int_distribution with narrow integral types
674// (char/signed char/unsigned char/short/bool), but libc++ rejects them with a
675// hard static_assert ("IntType must be a supported integer type"). Promote such
676// types to a width the standard guarantees, preserving signedness, so the same
677// `next<T>` works across both standard libraries (e.g. Apple clang / libc++).
678template <typename T>
679using uniform_int_t = std::conditional_t<
680 (sizeof(T) >= sizeof(short)), T,
681 std::conditional_t<std::is_signed_v<T>, int, unsigned int>>;
682
683} // namespace detail
684
685// Returns a uniformly random number in [0, right)
686// O(1).
687template <typename T> T next(T right) {
688 detail::ensure_registered();
689 if constexpr (std::is_integral_v<T>) {
690 tgen_ensure(right >= 1, "value for `next` must be valid");
691 return static_cast<T>(
692 std::uniform_int_distribution<detail::uniform_int_t<T>>(
693 0,
694 static_cast<detail::uniform_int_t<T>>(right) - 1)(detail::rng));
695 } else if constexpr (std::is_floating_point_v<T>) {
696 tgen_ensure(right >= 0, "value for `next` must be valid");
697 return std::uniform_real_distribution<T>(0, right)(detail::rng);
698 } else
699 throw detail::error("invalid type for next (" +
700 std::string(typeid(T).name()) + ")");
701}
702
703// Returns a uniformly random number in [left, right].
704// For floating-point types, uses uniform_real_distribution ([left, right) in
705// C++), equivalent to [left, right] because the right endpoint has probability
706// zero.
707// O(1).
708template <typename T> T next(T left, T right) {
709 detail::ensure_registered();
710 tgen_ensure(left <= right, "range for `next` must be valid");
711 if constexpr (std::is_integral_v<T>)
712 return static_cast<T>(
713 std::uniform_int_distribution<detail::uniform_int_t<T>>(
714 static_cast<detail::uniform_int_t<T>>(left),
715 static_cast<detail::uniform_int_t<T>>(right))(detail::rng));
716 else if constexpr (std::is_floating_point_v<T>)
717 return std::uniform_real_distribution<T>(left, right)(detail::rng);
718 else
719 throw detail::error("invalid type for next (" +
720 std::string(typeid(T).name()) + ")");
721}
722
723// Skewed next.
724//
725// Returns a random number in [0, right) with a bias controlled by `w`.
726// - w = 0:
727// Uniform distribution.
728// - w > 0:
729// Returns the maximum of (w + 1) independent uniform samples.
730// Biases the distribution toward larger values.
731// The resulting density is proportional to:
732// f(x) = x^w
733// In particular:
734// w = 1 -> linear bias
735// w = 2 -> quadratic bias
736// w = 3 -> cubic bias
737// - w < 0:
738// Returns the minimum of (-w + 1) independent uniform samples.
739// Symmetric to the w > 0 case.
740// The continuous version corresponds to Beta distributions:
741// w > 0 -> Beta(w + 1, 1)
742// w < 0 -> Beta(1, -w + 1)
743// For |w| > 5, the distribution is approximate.
744// O(1).
745template <typename T> T wnext(T right, int w) {
746 // For small |w|, use the naive approach.
747 if (abs(w) <= 5) {
748 T val = next<T>(right);
749 for (int i = 0; i < w; ++i)
750 val = std::max(val, next<T>(right));
751 for (int i = 0; i < -w; ++i)
752 val = std::min(val, next<T>(right));
753 return val;
754 }
755
756 // O(1) way.
757 double x, r = next<double>(0, 1);
758
759 if (w >= 0) {
760 x = std::pow(r, 1.0 / (w + 1));
761 } else {
762 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
763 }
764
765 return T(x * right);
766}
767
768// Returns a random number in [left, right] with a bias controlled by `w`.
769// O(1).
770template <typename T> T wnext(T left, T right, int w) {
771 // For small |w|, use the naive approach.
772 if (abs(w) <= 5) {
773 T val = next<T>(left, right);
774 for (int i = 0; i < w; ++i)
775 val = std::max(val, next<T>(left, right));
776 for (int i = 0; i < -w; ++i)
777 val = std::min(val, next<T>(left, right));
778 return val;
779 }
780
781 // O(1) way.
782 double x, r = next<double>(0, 1);
783
784 if (w >= 0) {
785 x = std::pow(r, 1.0 / (w + 1));
786 } else {
787 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
788 }
789
790 return left + T(x * (right - left));
791}
792
793namespace detail {
794
795// Uniformly random 128 bit number in [0, total).
796// O(1) expected.
797inline u128 next128(u128 total) {
798 tgen_ensure(total > 0, "next128: total must be positive");
799
800 // Largest multiple of total less than 2^128.
801 u128 limit = (u128(-1) / total) * total;
802
803 while (true) {
804 // Generate uniform 128-bit random number.
805 u128 r = (u128(next<uint64_t>(0, std::numeric_limits<uint64_t>::max()))
806 << 64) |
807 next<uint64_t>(0, std::numeric_limits<uint64_t>::max());
808
809 if (r < limit)
810 return r % total;
811 }
812}
813
814} // namespace detail
815
816// Weighted sampler.
817//
818// Generates indices with probability proportional to `distribution`, using
819// alias method.
820//
821// Internally, integral weights are accumulated in unsigned __int128 (exact);
822// floating-point weights are accumulated in double.
823// <O(n), O(1)>.
824template <typename T> struct weighted_sampler {
825 static_assert(std::is_arithmetic_v<T>,
826 "weighted_sampler requires an arithmetic weight type");
827
828 // Internal storage type: `u128` for integral inputs (exact arithmetic),
829 // `double` for floating-point inputs.
830 using storage_t =
832
833 int n_;
834 std::vector<storage_t> weight_;
835 std::vector<int> alias_;
836 storage_t total_;
837
838 // Creates an alias method for generating indices with probability
839 // proportional to the distribution.
840 // O(n).
841 weighted_sampler(const std::vector<T> &distribution)
842 : n_(distribution.size()), alias_(n_) {
843 tgen_ensure(distribution.size() > 0,
844 "weighted_sampler: distribution must be non-empty");
845 for (const auto &w : distribution)
846 tgen_ensure(w >= 0,
847 "weighted_sampler: distribution must be non-negative");
848
849 total_ = std::accumulate(distribution.begin(), distribution.end(),
850 storage_t(0));
851
852 std::queue<int> big, small;
853 for (int i = 0; i < n_; ++i) {
854 weight_.push_back(storage_t(n_) * storage_t(distribution[i]));
855 if (weight_[i] < total_)
856 small.push(i);
857 else
858 big.push(i);
859 }
860
861 while (!small.empty() and !big.empty()) {
862 int s = small.front();
863 small.pop();
864 int b = big.front();
865 big.pop();
866
867 alias_[s] = b;
868
869 weight_[b] -= total_ - weight_[s];
870 if (weight_[b] < total_)
871 small.push(b);
872 else
873 big.push(b);
874 }
875
876 detail::tgen_ensure_against_bug(
877 small.empty(), "weighted_sampler: small must be empty");
878
879 // The remaining elements should have weight equal to total and be
880 // assigned to themselves.
881 while (!big.empty()) {
882 int b = big.front();
883 big.pop();
884 if constexpr (std::is_integral_v<T>) {
885 detail::tgen_ensure_against_bug(
886 weight_[b] == total_,
887 "weighted_sampler: weight of big element must be total");
888 }
889 alias_[b] = b;
890 }
891 }
892 weighted_sampler(const std::initializer_list<T> &distribution)
893 : weighted_sampler(std::vector<T>(distribution)) {}
894
895 // Uniformly random value in [0, total). Overloaded so next() can dispatch
896 // at compile time to the right primitive for the chosen `storage_t`.
897 static detail::u128 sample_below(detail::u128 total) {
898 return detail::next128(total);
899 }
900 static double sample_below(double total) {
901 return tgen::next<double>(0, total);
902 }
903
904 // Generates a random index with probability proportional to the
905 // distribution.
906 // O(1).
907 size_t next() const {
908 int i = tgen::next<int>(0, n_ - 1);
909 return sample_below(total_) < weight_[i] ? i : alias_[i];
910 }
911};
912template <typename T>
913weighted_sampler(const std::vector<T> &) -> weighted_sampler<T>;
914template <typename T>
915weighted_sampler(const std::initializer_list<T> &) -> weighted_sampler<T>;
916
917// Returns i with probability proportional to distribution[i].
918// O(|distribution|).
919template <typename T>
920size_t next_by_distribution(const std::vector<T> &distribution) {
921 return weighted_sampler(distribution).next();
922}
923template <typename T>
924size_t next_by_distribution(const std::initializer_list<T> &distribution) {
925 return next_by_distribution(std::vector<T>(distribution));
926}
927
928// Returns a vector of k indices with probability proportional to
929// `distribution`. Uses alias method.
930// O(k + |distribution|).
931template <typename T>
933 const std::vector<T> &distribution) {
934 tgen_ensure(distribution.size() > 0, "distribution must be non-empty");
935 tgen_ensure(k >= 0, "number of elements to choose must be non-negative");
936
937 weighted_sampler am(distribution);
938 std::vector<int> res;
939 for (int i = 0; i < k; ++i)
940 res.push_back(am.next());
941 return res;
942}
943template <typename T>
944std::vector<int>
945many_by_distribution(int k, const std::initializer_list<T> &distribution) {
946 return many_by_distribution(k, std::vector<T>(distribution));
947}
948
949// Shuffles [first, last) inplace uniformly, for RandomAccessIterator.
950// O(|container|).
951template <typename It> void shuffle(It first, It last) {
952 if (first == last)
953 return;
954
955 for (It i = first + 1; i != last; ++i)
956 std::iter_swap(i, first + next(0, static_cast<int>(i - first)));
957}
958
959// Shuffles container uniformly.
960// O(|container|).
961template <typename C> [[nodiscard]] auto shuffled(const C &container) {
962 if constexpr (detail::is_associative_container<C>::value) {
963 std::vector<typename C::value_type> vec(container.begin(),
964 container.end());
965 shuffle(vec.begin(), vec.end());
966 return vec;
967 } else {
968 auto new_container = container;
969 shuffle(new_container.begin(), new_container.end());
970 return new_container;
971 }
972}
973template <typename T>
974[[nodiscard]] std::vector<T> shuffled(const std::initializer_list<T> &il) {
975 return shuffled(std::vector<T>(il));
976}
977
978// Returns a random element from [first, last) uniformly.
979// O(1) for random_access_iterator, O(|last - first|) otherwise.
980template <typename It> typename It::value_type pick(It first, It last) {
981 int size = std::distance(first, last);
982 tgen_ensure(size > 0, "cannot pick from empty range");
983 It it = first;
984 std::advance(it, next(0, size - 1));
985 return *it;
986}
987
988// Returns a random element from container uniformly.
989// O(1) for random_access_iterator, O(|container|) otherwise.
990template <typename C> typename C::value_type pick(const C &container) {
991 return pick(container.begin(), container.end());
992}
993template <typename T> T pick(const std::initializer_list<T> &il) {
994 return pick(std::vector<T>(il));
995}
996
997// Returns container[i] with probability proportional to distribution[i].
998// O(1) for random_access_iterator, O(|container|) otherwise.
999template <typename C, typename T>
1000typename C::value_type pick_by_distribution(const C &container,
1001 std::vector<T> distribution) {
1002 tgen_ensure(container.size() == distribution.size(),
1003 "container and distribution must have the same size");
1004 auto it = container.begin();
1005 std::advance(it, next_by_distribution(distribution));
1006 return *it;
1007}
1008template <typename C, typename T>
1009typename C::value_type
1010pick_by_distribution(const C &container,
1011 const std::initializer_list<T> &distribution) {
1012 return pick_by_distribution(container, std::vector<T>(distribution));
1013}
1014template <typename T, typename U>
1015T pick_by_distribution(const std::initializer_list<T> &il,
1016 const std::vector<U> &distribution) {
1017 return pick_by_distribution(std::vector<T>(il), distribution);
1018}
1019template <typename T, typename U>
1020T pick_by_distribution(const std::initializer_list<T> &il,
1021 const std::initializer_list<U> &distribution) {
1022 return pick_by_distribution(std::vector<T>(il),
1023 std::vector<U>(distribution));
1024}
1025
1026// Chooses k values uniformly from container, as in a subsequence of size k.
1027// Returns a copy. O(|container|).
1028template <typename C> C choose(const C &container, int k) {
1029 tgen_ensure(0 < k and k <= static_cast<int>(container.size()),
1030 "number of elements to choose must be valid");
1031 std::vector<typename C::value_type> new_vec;
1032 C new_container;
1033 int need = k, left = container.size();
1034 for (auto cur_it = container.begin(); cur_it != container.end(); ++cur_it) {
1035 if (next(1, left--) <= need) {
1036 new_container.insert(new_container.end(), *cur_it);
1037 need--;
1038 }
1039 }
1040 return new_container;
1041}
1042template <typename T>
1043std::vector<T> choose(const std::initializer_list<T> &il, int k) {
1044 return choose(std::vector<T>(il), k);
1045}
1046
1047// Number distinct generator for integral types.
1048// Optimized for performance (unordered_map virtual list; gen_list uses array
1049// pool, complement, or sparse sampling).
1050template <typename T> struct distinct_range {
1051 T left_, right_;
1052 T num_available_;
1053 std::unordered_map<T, T> virtual_list_;
1054
1055 // When the range fits in memory, sample via array Fisher–Yates.
1056 static constexpr size_t array_pool_max = size_t{1} << 23;
1057
1058 // Generator of distinct values in [left, right].
1059 distinct_range(T left, T right)
1060 : left_(left), right_(right), num_available_(right - left + 1) {}
1061
1062 // Returns the number of distinct values left to generate.
1063 T size() const { return num_available_; }
1064
1065 // Generates a random value in [left_, right_] that has not been generated
1066 // yet.
1067 // O(log n).
1068 T gen() {
1069 // One iteration of Fisher–Yates.
1070 tgen_ensure(size() > 0, "distinct_range: no more values to generate");
1071
1072 T i = next<T>(0, size() - 1);
1073 T j = size() - 1;
1074
1075 auto vi_it = virtual_list_.find(i);
1076 T vi = vi_it == virtual_list_.end() ? i : vi_it->second;
1077 auto vj_it = virtual_list_.find(j);
1078 T vj = vj_it == virtual_list_.end() ? j : vj_it->second;
1079 virtual_list_[i] = vj;
1080
1081 --num_available_;
1082
1083 return vi + left_;
1084 }
1085
1086 // Generates a list of distinct values.
1087 // Optimized for performance (array pool, complement, or sparse sampling).
1088 // O(size) when the range fits in memory; O(size log range) otherwise.
1089 auto gen_list(int count) {
1090 tgen_ensure(count >= 0, "distinct_range: size must be nonnegative");
1091 tgen_ensure(count <= num_available_,
1092 "distinct_range: no more values to generate");
1093
1094 size_t range_size = right_ - left_ + 1;
1095 size_t sample_count = count;
1096
1097 std::vector<T> res;
1098 if (sample_count > 0) {
1099 if (range_size <= array_pool_max)
1100 res = sample_from_pool(sample_count, range_size);
1101 else if (sample_count * 2 > range_size)
1102 res = sample_complement(sample_count, range_size);
1103 else
1104 res = sample_sparse(sample_count);
1105 }
1106
1107 num_available_ -= count;
1108 virtual_list_.clear();
1109 return typename list<T>::value(res);
1110 }
1111
1112 // Generates all distinct values.
1113 // O(n) when the range fits in memory; O(n log n) otherwise.
1114 auto gen_all() { return gen_list(size()); }
1115
1116 private:
1117 // Samples count distinct values via array Fisher–Yates on [left_, right_].
1118 // O(range_size) time and memory.
1119 std::vector<T> sample_from_pool(size_t count, size_t range_size) {
1120 std::vector<T> pool(range_size);
1121 std::iota(pool.begin(), pool.end(), left_);
1122 for (size_t i = 0; i < count; ++i) {
1123 size_t j = next<size_t>(i, range_size - 1);
1124 std::swap(pool[i], pool[j]);
1125 }
1126 pool.resize(count);
1127 return pool;
1128 }
1129
1130 // Samples count distinct values by excluding range_size - count values.
1131 // O(range_size + (range_size - count) log(range_size)).
1132 std::vector<T> sample_complement(size_t count, size_t range_size) {
1133 size_t exclude_count = range_size - count;
1134 std::unordered_set<T> excluded;
1135 excluded.reserve(exclude_count * 2);
1136
1137 if (exclude_count <= array_pool_max) {
1138 for (T value : sample_from_pool(exclude_count, range_size))
1139 excluded.insert(value);
1140 } else {
1141 for (T value : sample_sparse(exclude_count))
1142 excluded.insert(value);
1143 }
1144
1145 std::vector<T> res;
1146 res.reserve(count);
1147 for (T value = left_; value <= right_; ++value) {
1148 if (!excluded.count(value))
1149 res.push_back(value);
1150 }
1151 detail::tgen_ensure_against_bug(
1152 res.size() == count, "distinct_range: complement sampling failed");
1153 return res;
1154 }
1155
1156 // Samples count distinct values via sparse-map Fisher–Yates.
1157 // O(count log(range_size)).
1158 std::vector<T> sample_sparse(size_t count) {
1159 std::unordered_map<T, T> local_virtual;
1160 local_virtual.reserve(count * 2);
1161 T remaining = range_span();
1162 std::vector<T> res;
1163 res.reserve(count);
1164 for (size_t step = 0; step < count; ++step) {
1165 T i = next<T>(0, remaining - 1);
1166 T j = remaining - 1;
1167
1168 auto vi_it = local_virtual.find(i);
1169 T vi = vi_it == local_virtual.end() ? i : vi_it->second;
1170 auto vj_it = local_virtual.find(j);
1171 T vj = vj_it == local_virtual.end() ? j : vj_it->second;
1172 local_virtual[i] = vj;
1173
1174 res.push_back(vi + left_);
1175 --remaining;
1176 }
1177 return res;
1178 }
1179
1180 // Returns right_ - left_ + 1.
1181 // O(1).
1182 T range_span() { return right_ - left_ + 1; }
1183};
1184
1185// Distinct generator for containers.
1186template <typename T> struct distinct_container {
1187 std::vector<T> list_;
1188 distinct_range<size_t> idx_;
1189
1190 // Creates a distinct container generator for the given container.
1191 template <typename C>
1192 distinct_container(const C &container)
1194 idx_(0, static_cast<int>(container.size()) - 1) {}
1195 distinct_container(const std::initializer_list<T> &il)
1196 : distinct_container(std::vector<T>(il)) {}
1197
1198 // Returns the number of distinct elements left to generate.
1199 size_t size() const { return idx_.size(); }
1200
1201 // Generates a random element from container uniformly.
1202 // O(log n).
1203 T gen() { return list_[idx_.gen()]; }
1204
1205 // Generates a list of distinct values.
1206 // O(size * log(n)).
1207 auto gen_list(int size) {
1208 std::vector<T> res;
1209 for (int i = 0; i < size; ++i)
1210 res.push_back(gen());
1211 return typename list<T>::value(res);
1212 }
1213
1214 // Generates all distinct values.
1215 // O(n log(n))
1216 auto gen_all() {
1217 std::vector<T> res;
1218 while (size() > 0)
1219 res.push_back(gen());
1220 return typename list<T>::value(res);
1221 }
1222};
1223template <typename C>
1224distinct_container(const C &) -> distinct_container<typename C::value_type>;
1225
1226/************
1227 * *
1228 * OPTS *
1229 * *
1230 ************/
1231
1232/*
1233 * Opts - options given to the generator.
1234 *
1235 * Incompatible with testlib.
1236 *
1237 * Opts are a list of either positional or named options.
1238 *
1239 * Named options are given in one of the following formats:
1240 * 1) -keyname=value or --keyname=value (ex. -n=10 , --test-count=20)
1241 * 2) -keyname value or --keyname value (ex. -n 10 , --test-count 20)
1242 *
1243 * Positional options are numbered from 0 sequentially.
1244 * For example, for "10 -n=20 str" positional option 1 is the string "str".
1245 */
1246
1247/*
1248 * C++ version selection.
1249 */
1250
1251// Sets C++ version.
1252inline void set_cpp_version(int version) {
1253 detail::cpp = detail::cpp_value(version);
1254}
1255
1256/*
1257 * Compiler selection.
1258 */
1259
1260// GCC compiler type.
1261inline compiler_value gcc(int major = 0, int minor = 0) {
1262 return {compiler_kind::gcc, major, minor};
1263}
1264
1265// Clang compiler type.
1266inline compiler_value clang(int major = 0, int minor = 0) {
1267 return {compiler_kind::clang, major, minor};
1268}
1269
1270// Sets compiler.
1271inline void set_compiler(compiler_value compiler) {
1272 detail::compiler.kind_ = compiler.kind_;
1273 detail::compiler.major_ = compiler.major_;
1274 detail::compiler.minor_ = compiler.minor_;
1275}
1276
1277namespace detail {
1278
1279// Processes special opt flags.
1280// Returns true if the key is a special opt flag.
1281inline bool process_special_opt_flags(std::string &key) {
1282 // Checks for gen::CPP=17|20|23
1283 if (key.find("tgen::CPP:") == 0) {
1284 int prefix_len = std::string("tgen::CPP:").size();
1285 tgen_ensure(static_cast<int>(key.size()) == prefix_len + 2 and
1286 std::isdigit(key[prefix_len]) and
1287 std::isdigit(key[prefix_len + 1]),
1288 "invalid CPP format");
1289 int version = std::stoi(key.substr(prefix_len, 2));
1290 set_cpp_version(version);
1291 return true;
1292 }
1293
1294 // Checks for tgen::(GCC|CLANG) or
1295 // tgen::(GCC|CLANG):(version|version.minor).
1296 compiler_kind kind;
1297 size_t prefix_len = 0;
1298
1299 if (key.find("tgen::GCC") == 0) {
1300 kind = compiler_kind::gcc;
1301 prefix_len = std::string("tgen::GCC").size();
1302 } else if (key.find("tgen::CLANG") == 0) {
1303 kind = compiler_kind::clang;
1304 prefix_len = std::string("tgen::CLANG").size();
1305 } else {
1306 return false;
1307 }
1308
1309 if (key.size() == prefix_len) {
1310 set_compiler(compiler_value(kind, 0, 0));
1311 return true;
1312 }
1313
1314 tgen_ensure(key[prefix_len] == ':', "invalid compiler format");
1315 ++prefix_len; // for ':'.
1316
1317 std::string inside = key.substr(prefix_len, key.size() - prefix_len);
1318 int major = 0, minor = 0;
1319
1320 size_t dot = inside.find('.');
1321 if (dot == std::string::npos) {
1322 tgen_ensure(!inside.empty() and
1323 std::all_of(inside.begin(), inside.end(), ::isdigit),
1324 "invalid compiler version");
1325 major = std::stoi(inside);
1326 } else {
1327 std::string maj = inside.substr(0, dot);
1328 std::string min = inside.substr(dot + 1);
1329
1330 tgen_ensure(!maj.empty() and
1331 std::all_of(maj.begin(), maj.end(), ::isdigit) and
1332 maj.size() <= 3,
1333 "invalid compiler major version");
1334 tgen_ensure(!min.empty() and
1335 std::all_of(min.begin(), min.end(), ::isdigit) and
1336 min.size() <= 3,
1337 "invalid compiler minor version");
1338
1339 major = std::stoi(maj);
1340 minor = std::stoi(min);
1341 }
1342
1343 set_compiler(compiler_value(kind, major, minor));
1344
1345 return true;
1346}
1347
1348inline std::vector<std::string>
1349 pos_opts; // Dictionary containing the positional parsed opts.
1350inline std::map<std::string, std::string>
1351 named_opts; // Global dictionary the named parsed opts.
1352
1353template <typename T> T get_opt(const std::string &value) {
1354 try {
1355 if constexpr (std::is_same_v<T, bool>) {
1356 if (value == "true" or value == "1")
1357 return true;
1358 if (value == "false" or value == "0")
1359 return false;
1360 } else if constexpr (std::is_integral_v<T>) {
1361 if constexpr (std::is_unsigned_v<T>)
1362 return static_cast<T>(std::stoull(value));
1363 else
1364 return static_cast<T>(std::stoll(value));
1365 } else if constexpr (std::is_floating_point_v<T>)
1366 return static_cast<T>(std::stold(value));
1367 else
1368 return value; // Default: std::string.
1369 } catch (...) {
1370 }
1371
1372 throw error("invalid value `" + value + "` for type " + typeid(T).name());
1373}
1374
1375inline void parse_opts(int argc, char **argv) {
1376 // Parses the opts into `pos_opts` vector and `named_opts`
1377 // map. Starting from 1 to ignore the name of the executable.
1378 for (int i = 1; i < argc; ++i) {
1379 std::string key(argv[i]);
1380
1381 if (process_special_opt_flags(key))
1382 continue;
1383
1384 if (key[0] == '-') {
1385 tgen_ensure(key.size() > 1,
1386 "invalid opt (" + std::string(argv[i]) + ")");
1387 if ('0' <= key[1] and key[1] <= '9') {
1388 // This case is a positional negative number argument.
1389 pos_opts.push_back(key);
1390 continue;
1391 }
1392
1393 // Pops first char '-'.
1394 key = key.substr(1);
1395 } else {
1396 // This case is a positional argument that does not start with '-'.
1397 pos_opts.push_back(key);
1398 continue;
1399 }
1400
1401 // Pops a possible second char '-'.
1402 if (key[0] == '-') {
1403 tgen_ensure(key.size() > 1,
1404 "invalid opt (" + std::string(argv[i]) + ")");
1405
1406 // Pops first char '-'.
1407 key = key.substr(1);
1408 }
1409
1410 // Assumes that, if it starts with '-' and second char is not a digit,
1411 // then it is a <key, value> pair.
1412 // 1 or 2 chars '-' have already been popped.
1413
1414 std::size_t eq = key.find('=');
1415 if (eq != std::string::npos) {
1416 // This is the '--key=value' case.
1417 std::string value = key.substr(eq + 1);
1418 key = key.substr(0, eq);
1419 tgen_ensure(!key.empty() and !value.empty(),
1420 "expected non-empty key/value in opt (" +
1421 std::string(argv[i]) + ")");
1422 tgen_ensure(named_opts.count(key) == 0,
1423 "cannot have repeated keys");
1424 named_opts[key] = value;
1425 } else {
1426 // This is the '--key value' case.
1427 tgen_ensure(named_opts.count(key) == 0,
1428 "cannot have repeated keys");
1429 tgen_ensure(argv[i + 1], "value cannot be empty");
1430 named_opts[key] = std::string(argv[i + 1]);
1431 ++i;
1432 }
1433 }
1434}
1435
1436inline void set_seed(int argc, char **argv) {
1437 std::vector<uint32_t> seed;
1438
1439 // Starting from 1 to ignore the name of the executable.
1440 for (int i = 1; i < argc; ++i) {
1441 // We append the number of chars, and then the list of chars.
1442 int size_pos = seed.size();
1443 seed.push_back(0);
1444 for (char *s = argv[i]; *s != '\0'; ++s) {
1445 ++seed[size_pos];
1446 seed.push_back(*s);
1447 }
1448 }
1449 std::seed_seq seq(seed.begin(), seed.end());
1450 rng.seed(seq);
1451}
1452
1453} // namespace detail
1454
1455// Returns true if there is an opt at a given index.
1456inline bool has_opt(std::size_t index) {
1457 detail::ensure_registered();
1458 return index < detail::pos_opts.size();
1459}
1460
1461// Returns true if there is an opt with a given key.
1462inline bool has_opt(const std::string &key) {
1463 detail::ensure_registered();
1464 return detail::named_opts.count(key) != 0;
1465}
1466template <typename K>
1467std::enable_if_t<std::is_same_v<K, char>, bool> has_opt(K key) {
1468 return has_opt(std::string(1, key));
1469}
1470
1471// Returns the parsed opt by a given index. If no opts with the given index are
1472// found, returns the given default_value.
1473template <typename T>
1474T opt(size_t index, std::optional<T> default_value = std::nullopt) {
1475 detail::ensure_registered();
1476 if (!has_opt(index)) {
1477 if (default_value)
1478 return *default_value;
1479 throw detail::error("cannot find opt at index " +
1480 std::to_string(index));
1481 }
1482 return detail::get_opt<T>(detail::pos_opts[index]);
1483}
1484
1485// Returns the parsed opt by a given key. If no opts with the given key are
1486// found, returns the given default_value.
1487template <typename T>
1488T opt(const std::string &key, std::optional<T> default_value = std::nullopt) {
1489 detail::ensure_registered();
1490 if (!has_opt(key)) {
1491 if (default_value)
1492 return *default_value;
1493 throw detail::error("cannot find opt with key " + key);
1494 }
1495 return detail::get_opt<T>(detail::named_opts[key]);
1496}
1497template <typename T, typename K>
1498std::enable_if_t<std::is_same_v<K, char>, T>
1499opt(K key, std::optional<T> default_value = std::nullopt) {
1500 return opt<T>(std::string(1, key), default_value);
1501}
1502
1503// Registers generator by initializing rng and parsing opts.
1504inline void register_gen(int argc, char **argv) {
1505 detail::set_seed(argc, argv);
1506
1507 detail::pos_opts.clear();
1508 detail::named_opts.clear();
1509 detail::parse_opts(argc, argv);
1510
1511 detail::registered = true;
1512}
1513
1514// Registers generator by initializing rng with a given seed.
1515inline void register_gen(std::optional<long long> seed = std::nullopt) {
1516 if (seed)
1517 detail::rng.seed(*seed);
1518 else
1519 detail::rng.seed();
1520
1521 detail::pos_opts.clear();
1522 detail::named_opts.clear();
1523
1524 detail::registered = true;
1525}
1526
1527/************
1528 * *
1529 * LIST *
1530 * *
1531 ************/
1532
1533/*
1534 * List generator.
1535 *
1536 * List of integral types.
1537 */
1538
1539template <typename T> struct list : gen_base<list<T>> {
1540 int size_; // Size of list.
1541 T value_l_, value_r_; // Range of defined values.
1542 std::set<T> values_; // Set of values. If empty, use range; if not,
1543 // represents the possible values, and the range
1544 // represents the index in this set.
1545 std::map<T, int>
1546 value_idx_in_set_; // Index of every value in the set above.
1547 mutable std::vector<std::pair<T, T>>
1548 val_range_; // Range of values of each index.
1549 mutable std::vector<std::vector<int>> neigh_; // Adjacency list of equality.
1550 std::vector<std::set<int>>
1551 diff_restrictions_; // All different restrictions.
1552 bool index_constraints_{
1553 false}; // True after fix/equal narrows per-index generation.
1554 mutable bool uses_full_range_{
1555 false}; // If true, every index uses [value_l_, value_r_] lazily.
1556
1557 // Creates generator for lists of size 'size', with random T in [value_left,
1558 // value_right].
1559 list(int size, T value_left, T value_right)
1560 : size_(size), value_l_(value_left), value_r_(value_right),
1561 uses_full_range_(true) {
1562 tgen_ensure(size_ > 0, "list: size must be positive");
1563 tgen_ensure(value_l_ <= value_r_, "list: value range must be valid");
1564 }
1565
1566 // Creates list with value set.
1567 list(int size, std::set<T> values)
1568 : size_(size), values_(values), index_constraints_(true) {
1569 tgen_ensure(size_ > 0, "list: size must be positive");
1570 tgen_ensure(!values.empty(), "list: value set must be non-empty");
1571 value_l_ = 0, value_r_ = values.size() - 1;
1572 val_range_.assign(size_, {value_l_, value_r_});
1573 int idx = 0;
1574 for (T val : values_)
1575 value_idx_in_set_[val] = idx++;
1576 }
1577
1578 // Restricts lists for list[idx] = val.
1579 list &fix(int idx, T val) {
1580 tgen_ensure(0 <= idx and idx < size_, "list: index must be valid");
1581 ensure_val_range_materialized();
1582 if (values_.size() == 0) {
1583 auto &[left, right] = val_range_[idx];
1584 if (left == right and value_l_ != value_r_) {
1585 tgen_ensure(left == val,
1586 "list: must not set to two different values");
1587 } else {
1588 tgen_ensure(left <= val and val <= right,
1589 "list: value must be in the defined range");
1590 }
1591 left = right = val;
1592 } else {
1593 tgen_ensure(values_.count(val),
1594 "list: value must be in the set of values");
1595 auto &[left, right] = val_range_[idx];
1596 int new_val = value_idx_in_set_[val];
1597 tgen_ensure(left <= new_val and new_val <= right,
1598 "list: must not set to two different values");
1599 left = right = new_val;
1600 }
1601 index_constraints_ = true;
1602 return *this;
1603 }
1604
1605 // Restricts lists for list[idx_1] = list[idx_2].
1606 list &equal(int idx_1, int idx_2) {
1607 tgen_ensure(0 <= std::min(idx_1, idx_2) and
1608 std::max(idx_1, idx_2) < size_,
1609 "list: indices must be valid");
1610 if (idx_1 == idx_2)
1611 return *this;
1612
1613 ensure_val_range_materialized();
1614 ensure_neigh_allocated();
1615 index_constraints_ = true;
1616 neigh_[idx_1].push_back(idx_2);
1617 neigh_[idx_2].push_back(idx_1);
1618 return *this;
1619 }
1620
1621 // Restricts lists for list[S] to be equal, for given subset S of indices.
1622 list &equal(std::set<int> indices) {
1623 if (!indices.empty()) {
1624 std::set<int>::iterator beg = indices.begin();
1625 for (auto it = std::next(beg); it != indices.end(); ++it)
1626 equal(*beg, *it);
1627 }
1628 return *this;
1629 }
1630
1631 // Restricts lists for list[left..right] to have all equal values.
1632 list &equal_range(int left, int right) {
1633 tgen_ensure(0 <= left and left <= right and right < size_,
1634 "list: range indices must be valid");
1635 for (int i = left; i < right; ++i)
1636 equal(i, i + 1);
1637 return *this;
1638 }
1639
1640 // Restricts lists for all equal elements.
1641 list &all_equal() { return equal_range(0, size_ - 1); }
1642
1643 // Restricts lists for list[S] to be different (distinct), for given subset
1644 // S of indices. You cannot add two of these restrictions on sets that
1645 // intersect.
1646 list &different(std::set<int> indices) {
1647 if (!indices.empty())
1648 diff_restrictions_.push_back(indices);
1649 return *this;
1650 }
1651
1652 // Restricts lists for list[idx_1] != list[idx_2].
1653 list &different(int idx_1, int idx_2) {
1654 std::set<int> indices = {idx_1, idx_2};
1655 return different(indices);
1656 }
1657
1658 // Restricts lists for list[left..right] to have all different values.
1659 list &different_range(int left, int right) {
1660 tgen_ensure(0 <= left and left <= right and right < size_,
1661 "list: range indices must be valid");
1662 std::vector<int> indices(right - left + 1);
1663 std::iota(indices.begin(), indices.end(), left);
1664 return different(std::set<int>(indices.begin(), indices.end()));
1665 }
1666
1667 // Restricts lists for all different elements.
1669 std::vector<int> indices(size_);
1670 std::iota(indices.begin(), indices.end(), 0);
1671 return different(std::set<int>(indices.begin(), indices.end()));
1672 }
1673
1674 // List value.
1675 // Operations on a value are not random.
1677 using tgen_is_sequential_tag = detail::is_sequential_tag;
1678
1679 using value_type = T; // Value type, for templates.
1680 using std_type = std::vector<T>; // std type for value.
1681
1682 std::vector<T> vec_; // list.
1683 char sep_; // Separator for printing.
1684
1685 value(const std::vector<T> &vec) : vec_(vec), sep_(' ') {}
1686 value(const std::initializer_list<T> &il) : value(std::vector<T>(il)) {}
1687
1688 // Fetches size.
1689 int size() const { return vec_.size(); }
1690
1691 // Fetches position idx.
1692 T &operator[](int idx) {
1693 tgen_ensure(0 <= idx and idx < size(),
1694 "list: value: index out of bounds");
1695 return vec_[idx];
1696 }
1697 const T &operator[](int idx) const {
1698 tgen_ensure(0 <= idx and idx < size(),
1699 "list: value: index out of bounds");
1700 return vec_[idx];
1701 }
1702
1703 // Sorts values in non-decreasing order.
1704 // O(n log n).
1706 std::sort(vec_.begin(), vec_.end());
1707 return *this;
1708 }
1709
1710 // Reverses list.
1711 // O(n).
1713 std::reverse(vec_.begin(), vec_.end());
1714 return *this;
1715 }
1716
1717 // Sets the separator for the list, for printing.
1718 // O(1).
1719 value &separator(char sep) {
1720 sep_ = sep;
1721 return *this;
1722 }
1723
1724 // Concatenates two values.
1725 // Linear.
1726 value operator+(const value &rhs) const {
1727 std::vector<T> new_vec = vec_;
1728 for (int i = 0; i < rhs.size(); ++i)
1729 new_vec.push_back(rhs[i]);
1730 return value(new_vec);
1731 }
1732
1733 // Shuffles list uniformly.
1734 // O(n).
1736 for (int i = 0; i < size(); ++i)
1737 std::swap(vec_[i], vec_[next(0, size() - 1)]);
1738 return *this;
1739 }
1740
1741 // Returns a random element uniformly.
1742 // O(1).
1743 T pick() const { return vec_[next<int>(0, size() - 1)]; }
1744
1745 // Returns vec_[i] with probability proportional to distribution[i].
1746 // O(1).
1747 template <typename Dist>
1748 T pick_by_distribution(const std::vector<Dist> &distribution) const {
1749 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
1750 "value and distribution must have the same size");
1751 return vec_[next_by_distribution(distribution)];
1752 }
1753 template <typename Dist>
1754 T pick_by_distribution(
1755 const std::initializer_list<Dist> &distribution) const {
1756 return pick_by_distribution(std::vector<Dist>(distribution));
1757 }
1758
1759 // Chooses k values uniformly, as in a subsequence of size k.
1760 // O(n).
1761 value choose(int k) const {
1762 tgen_ensure(0 < k and k <= size(),
1763 "number of elements to choose must be valid");
1764 std::vector<T> new_vec;
1765 int need = k;
1766 for (int i = 0; need > 0; ++i) {
1767 int left = size() - i;
1768 if (next(1, left) <= need) {
1769 new_vec.push_back(vec_[i]);
1770 need--;
1771 }
1772 }
1773 return value(new_vec);
1774 }
1775
1776 // Prints to std::ostream, separated by sep_.
1777 friend std::ostream &operator<<(std::ostream &out, const value &val) {
1778 for (int i = 0; i < val.size(); ++i) {
1779 if (i > 0)
1780 out << val.sep_;
1781 out << val[i];
1782 }
1783 return out;
1784 }
1785
1786 // Gets a std::vector representing the value.
1787 auto to_std() const {
1788 if constexpr (!detail::is_generator_value<T>::value) {
1789 return vec_;
1790 } else {
1791 std::vector<typename T::std_type> vec;
1792 for (const auto &i : vec_)
1793 vec.push_back(i.to_std());
1794 return vec;
1795 }
1796 }
1797 };
1798
1799 // Generates list value.
1800 // Optimized for performance (unconstrained and all-different fast paths).
1801 // O(n log n).
1802 value gen() const {
1803 if (diff_restrictions_.empty()) {
1804 if (auto unconstrained = try_gen_unconstrained())
1805 return *unconstrained;
1806 }
1807 if (auto all_different = try_gen_all_different())
1808 return *all_different;
1809
1810 ensure_neigh_allocated();
1811 std::vector<T> vec(size_);
1812 std::vector<bool> defined_idx(
1813 size_, false); // For every index, if it has been set in `vec`.
1814
1815 std::vector<int> comp_id(size_, -1); // Component id of each index.
1816 std::vector<std::vector<int>> comp(size_); // Component of each comp-id.
1817 int comp_count = 0; // Number of different components.
1818
1819 // Defines value of entire component.
1820 auto define_comp = [&](int cur_comp, T val) {
1821 for (int idx : comp[cur_comp]) {
1822 tgen_ensure(!defined_idx[idx]);
1823 vec[idx] = val;
1824 defined_idx[idx] = true;
1825 }
1826 };
1827
1828 // Groups = components.
1829 {
1830 std::vector<bool> vis(size_, false); // Visited for each index.
1831 for (int idx = 0; idx < size_; ++idx)
1832 if (!vis[idx]) {
1833 T new_value;
1834 bool value_defined = false;
1835
1836 // BFS to visit the connected component, grouping equal
1837 // values.
1838 std::queue<int> q({idx});
1839 vis[idx] = true;
1840 std::vector<int> component;
1841 while (!q.empty()) {
1842 int cur_idx = q.front();
1843 q.pop();
1844
1845 component.push_back(cur_idx);
1846
1847 // Checks value.
1848 auto [l, r] = val_range_at(cur_idx);
1849 if (l == r) {
1850 if (!value_defined) {
1851 // We found the value.
1852 value_defined = true;
1853 new_value = l;
1854 } else if (new_value != l) {
1855 // We found a contradiction
1856 throw detail::contradiction_error(
1857 "list",
1858 "tried to set value to `" +
1859 std::to_string(new_value) +
1860 "`, but it was already set as `" +
1861 std::to_string(l) + "`");
1862 }
1863 }
1864
1865 for (int nxt_idx : neigh_[cur_idx]) {
1866 if (!vis[nxt_idx]) {
1867 vis[nxt_idx] = true;
1868 q.push(nxt_idx);
1869 }
1870 }
1871 }
1872
1873 // Group entire component, checking if value is defined.
1874 for (int cur_idx : component) {
1875 comp_id[cur_idx] = comp_count;
1876 comp[comp_id[cur_idx]].push_back(cur_idx);
1877 }
1878
1879 // Defines value if needed.
1880 if (value_defined)
1881 define_comp(comp_count, new_value);
1882
1883 ++comp_count;
1884 }
1885 }
1886
1887 // Initial parsing of different restrictions.
1888 std::vector<std::set<int>> diff_containing_comp_idx(comp_count);
1889 {
1890 int dist_id = 0;
1891 for (const std::set<int> &diff : diff_restrictions_) {
1892 // Checks if there are too many different values.
1893 if (static_cast<uint64_t>(diff.size() - 1) +
1894 static_cast<uint64_t>(value_l_) >
1895 static_cast<uint64_t>(value_r_))
1896 throw detail::contradiction_error(
1897 "list", "tried to generate " +
1898 std::to_string(diff.size()) +
1899 " different values, but the maximum is " +
1900 std::to_string(value_r_ - value_l_ + 1));
1901
1902 // Checks if two values in same component are marked as
1903 // different.
1904 std::set<int> comp_ids;
1905 for (int idx : diff) {
1906 if (comp_ids.count(comp_id[idx]))
1907 throw detail::contradiction_error(
1908 "list", "tried to set two indices as equal and "
1909 "different");
1910 comp_ids.insert(comp_id[idx]);
1911
1912 diff_containing_comp_idx[comp_id[idx]].insert(dist_id);
1913 }
1914 ++dist_id;
1915 }
1916 }
1917
1918 // If some value is in >= 3 sets, then there is a cycle.
1919 for (auto &diff_containing : diff_containing_comp_idx)
1920 if (diff_containing.size() >= 3)
1921 throw detail::complex_restrictions_error(
1922 "list",
1923 "one index cannot be in >= 3 'different' restrictions");
1924
1925 std::vector<bool> vis_diff(diff_restrictions_.size(), false);
1926 std::vector<bool> initially_defined_comp_idx(comp_count, false);
1927
1928 // Fills the value in a tree defined by "different" restrictions.
1929 auto define_tree = [&](int diff_id) {
1930 // The set `diff_restrictions_[diff_id]` can have some
1931 // values that are defined.
1932
1933 // Generates set of already defined values.
1934 std::set<T> defined_values;
1935 for (int idx : diff_restrictions_[diff_id])
1936 if (defined_idx[idx]) {
1937 // Checks if two values in `diff_restrictions_[dist_id]`
1938 // have been set to the same value
1939 if (defined_values.count(vec[idx]))
1940 throw detail::contradiction_error(
1941 "list",
1942 "tried to set two indices as equal and different");
1943
1944 defined_values.insert(vec[idx]);
1945 }
1946
1947 // Generates values in this root "different" restriction.
1948 {
1949 int new_value_count = diff_restrictions_[diff_id].size() -
1950 static_cast<int>(defined_values.size());
1951 std::vector<T> generated_values =
1952 generate_distinct_values(new_value_count, defined_values);
1953 auto val_it = generated_values.begin();
1954 for (int idx : diff_restrictions_[diff_id])
1955 if (defined_idx[idx]) {
1956 // The root can cover these components, but there should
1957 // not be any other defined in this tree.
1958 initially_defined_comp_idx[comp_id[idx]] = false;
1959 } else {
1960 define_comp(comp_id[idx], *val_it);
1961 ++val_it;
1962 }
1963 }
1964
1965 // BFS on the tree of "different" restrictions.
1966 std::queue<std::pair<int, int>> q; // {id, parent id}
1967 q.emplace(diff_id, -1);
1968 vis_diff[diff_id] = true;
1969 while (!q.empty()) {
1970 auto [cur_diff, parent] = q.front();
1971 q.pop();
1972
1973 std::set<int> neigh_diff;
1974 for (int idx : diff_restrictions_[cur_diff])
1975 for (int nxt_diff :
1976 diff_containing_comp_idx[comp_id[idx]]) {
1977 if (nxt_diff == cur_diff or nxt_diff == parent)
1978 continue;
1979
1980 // Cycle found.
1981 if (vis_diff[nxt_diff])
1982 throw detail::complex_restrictions_error(
1983 "list",
1984 "cycle found in 'different' restrictions");
1985
1986 neigh_diff.insert(nxt_diff);
1987 }
1988
1989 for (int nxt_diff : neigh_diff) {
1990 vis_diff[nxt_diff] = true;
1991 q.emplace(nxt_diff, cur_diff);
1992
1993 // Generates this "different" restriction.
1994 std::set<T> nxt_defined_values;
1995 for (int idx2 : diff_restrictions_[nxt_diff])
1996 if (defined_idx[idx2]) {
1997 // There cannot be any more defined. This case is
1998 // when there are values not covered by a single
1999 // "different" restriction in the tree.
2000 if (initially_defined_comp_idx[comp_id[idx2]])
2001 throw detail::complex_restrictions_error(
2002 "list");
2003
2004 nxt_defined_values.insert(vec[idx2]);
2005 }
2006 int new_value_count =
2007 diff_restrictions_[nxt_diff].size() -
2008 static_cast<int>(nxt_defined_values.size());
2009 std::vector<T> generated_values = generate_distinct_values(
2010 new_value_count, nxt_defined_values);
2011 auto val_it = generated_values.begin();
2012 for (int idx2 : diff_restrictions_[nxt_diff])
2013 if (!defined_idx[idx2]) {
2014 define_comp(comp_id[idx2], *val_it);
2015 ++val_it;
2016 }
2017 }
2018 }
2019 };
2020
2021 // Loops through "different" restrictions, sorts "different"
2022 // restrictions by number of defined components (non-increasing). This
2023 // guarantees that if there is a valid root (that covers all 'defined'),
2024 // we find it.
2025 {
2026 std::vector<std::pair<int, int>> defined_cnt_and_diff_idx;
2027 int dist_id = 0;
2028 for (const std::set<int> &diff : diff_restrictions_) {
2029 int defined_cnt = 0;
2030 for (int idx : diff)
2031 if (defined_idx[idx]) {
2032 ++defined_cnt;
2033 initially_defined_comp_idx[comp_id[idx]] = true;
2034 }
2035 defined_cnt_and_diff_idx.emplace_back(defined_cnt, dist_id);
2036 ++dist_id;
2037 }
2038
2039 std::sort(defined_cnt_and_diff_idx.rbegin(),
2040 defined_cnt_and_diff_idx.rend());
2041 for (auto [defined_cnt, diff_idx] : defined_cnt_and_diff_idx)
2042 if (!vis_diff[diff_idx])
2043 define_tree(diff_idx);
2044 }
2045
2046 // Loops through "different" restrictions do define the rest.
2047 for (std::size_t dist_id = 0; dist_id < diff_restrictions_.size();
2048 ++dist_id)
2049 if (!vis_diff[dist_id])
2050 define_tree(dist_id);
2051
2052 // Define final values. These values all should be random in [l, r], and
2053 // the "different" restrictions have already been processed. However,
2054 // there can be still equality restrictions, so we define entire
2055 // components.
2056 for (int idx = 0; idx < size_; ++idx)
2057 if (!defined_idx[idx])
2058 define_comp(comp_id[idx], next<T>(value_l_, value_r_));
2059
2060 if (!values_.empty()) {
2061 // Needs to fetch the values from the value set.
2062 std::vector<T> value_vec(values_.begin(), values_.end());
2063 for (T &val : vec)
2064 val = value_vec[val];
2065 }
2066
2067 return value(vec);
2068 }
2069
2070 private:
2071 // Materializes neigh_ after the first equality restriction.
2072 void ensure_neigh_allocated() const {
2073 if (neigh_.size() == static_cast<size_t>(size_))
2074 return;
2075 neigh_.assign(size_, {});
2076 }
2077
2078 // Materializes val_range_ after the first per-index restriction.
2079 void ensure_val_range_materialized() const {
2080 if (!uses_full_range_)
2081 return;
2082 val_range_.assign(size_, {value_l_, value_r_});
2083 uses_full_range_ = false;
2084 }
2085
2086 // Returns the allowed value range at index idx.
2087 std::pair<T, T> val_range_at(int idx) const {
2088 if (uses_full_range_)
2089 return {value_l_, value_r_};
2090 return val_range_[idx];
2091 }
2092
2093 // Generates a uniformly random list of k distinct values in `[value_l,
2094 // value_r]`, such that no value is in `forbidden_values`.
2095 std::vector<T>
2096 generate_distinct_values(int k, const std::set<T> &forbidden_values) const {
2097 for (auto forbidden : forbidden_values)
2098 tgen_ensure(value_l_ <= forbidden and forbidden <= value_r_);
2099 const T num_available =
2100 (value_r_ - value_l_ + 1) - forbidden_values.size();
2101 if (num_available < k)
2102 throw detail::complex_restrictions_error(
2103 "list", "not enough distinct values");
2104 if (forbidden_values.empty())
2105 return distinct_range<T>(value_l_, value_r_).gen_list(k).to_std();
2106
2107 std::map<T, T> virtual_list;
2108 std::vector<T> gen_list;
2109 for (int i = 0; i < k; ++i) {
2110 T j = next<T>(i, num_available - 1);
2111 T vj = virtual_list.count(j) ? virtual_list[j] : j;
2112 T vi = virtual_list.count(i) ? virtual_list[i] : i;
2113
2114 virtual_list[j] = vi, virtual_list[i] = vj;
2115
2116 gen_list.push_back(virtual_list[i]);
2117 }
2118
2119 for (T &val : gen_list)
2120 val += value_l_;
2121
2122 std::vector<std::pair<T, int>> values_sorted;
2123 for (std::size_t i = 0; i < gen_list.size(); ++i)
2124 values_sorted.emplace_back(gen_list[i], i);
2125 std::sort(values_sorted.begin(), values_sorted.end());
2126 auto cur_it = forbidden_values.begin();
2127 int smaller_forbidden_count = 0;
2128 for (auto [val, idx] : values_sorted) {
2129 while (cur_it != forbidden_values.end() and
2130 *cur_it <= val + smaller_forbidden_count)
2131 ++cur_it, ++smaller_forbidden_count;
2132 gen_list[idx] += smaller_forbidden_count;
2133 }
2134
2135 return gen_list;
2136 }
2137
2138 // If this generator has no constraints beyond [value_l_, value_r_],
2139 // returns independent uniform samples; otherwise returns std::nullopt.
2140 // O(n).
2141 std::optional<value> try_gen_unconstrained() const {
2142 if (!values_.empty() or index_constraints_)
2143 return std::nullopt;
2144
2145 std::vector<T> vec(size_);
2146 for (int i = 0; i < size_; ++i)
2147 vec[i] = next<T>(value_l_, value_r_);
2148 return value(vec);
2149 }
2150
2151 // If this generator is exactly all-distinct in [value_l_, value_r_],
2152 // returns a uniformly random list; otherwise returns std::nullopt.
2153 // Optimized for performance (distinct_range fast path).
2154 // O(n log n).
2155 std::optional<value> try_gen_all_different() const {
2156 if (!values_.empty() or diff_restrictions_.size() != 1)
2157 return std::nullopt;
2158
2159 const std::set<int> &diff = diff_restrictions_[0];
2160 if (static_cast<int>(diff.size()) != size_ or *diff.begin() != 0 or
2161 *diff.rbegin() != size_ - 1)
2162 return std::nullopt;
2163
2164 if (!neigh_.empty()) {
2165 for (const auto &adj : neigh_) {
2166 if (!adj.empty())
2167 return std::nullopt;
2168 }
2169 }
2170
2171 if (index_constraints_)
2172 return std::nullopt;
2173
2174 if (static_cast<long long>(size_) >
2175 static_cast<long long>(value_r_) - value_l_ + 1)
2176 throw detail::contradiction_error(
2177 "list", "tried to generate " + std::to_string(size_) +
2178 " different values, but the maximum is " +
2179 std::to_string(value_r_ - value_l_ + 1));
2180
2181 return distinct_range<T>(value_l_, value_r_).gen_list(size_);
2182 }
2183};
2184
2185/*******************
2186 * *
2187 * PERMUTATION *
2188 * *
2189 *******************/
2190
2191/*
2192 * Permutation generation.
2193 *
2194 * Permutation are defined always as numbers in [0, n), that is, 0-based.
2195 */
2196
2198 int size_; // Size of permutation.
2199 std::vector<std::pair<int, int>> defs_; // {idx, value}.
2200 std::optional<std::vector<int>> cycle_sizes_; // Cycle sizes.
2201
2202 // Creates generator for permutation of size 'size'.
2203 permutation(int size) : size_(size) {
2204 tgen_ensure(size_ > 0, "permutation: size must be positive");
2205 }
2206
2207 // Restricts permutations for permutation[idx] = val.
2208 permutation &fix(int idx, int val) {
2209 tgen_ensure(0 <= idx and idx < size_,
2210 "permutation: index must be valid");
2211 defs_.emplace_back(idx, val);
2212 return *this;
2213 }
2214
2215 // Restricts permutations for permutation to have cycle sizes.
2216 permutation &cycles(const std::vector<int> &cycle_sizes) {
2218 size_ == std::accumulate(cycle_sizes.begin(), cycle_sizes.end(), 0),
2219 "permutation: cycle sizes must add up to size of permutation");
2220 cycle_sizes_ = cycle_sizes;
2221 return *this;
2222 }
2223 permutation &cycles(const std::initializer_list<int> &cycle_sizes) {
2224 return cycles(std::vector<int>(cycle_sizes));
2225 }
2226
2227 // Permutation value.
2228 // Operations on a value are not random.
2230 using tgen_is_sequential_tag = detail::is_sequential_tag;
2231
2232 using std_type = std::vector<int>; // std type for value.
2233 std::vector<int> vec_; // Permutation.
2234 char sep_; // Separator for printing.
2235 bool add_1_; // If should add 1, for printing.
2236
2237 value(const std::vector<int> &vec)
2238 : vec_(vec), sep_(' '), add_1_(false) {
2239 tgen_ensure(!vec_.empty(), "permutation: value: cannot be empty");
2240 std::vector<bool> vis(vec_.size(), false);
2241 for (int i = 0; i < size(); ++i) {
2242 tgen_ensure(0 <= vec_[i] and
2243 vec_[i] < static_cast<int>(vec_.size()),
2244 "permutation: value: values must be from `0` to "
2245 "`size-1`");
2246 tgen_ensure(!vis[vec_[i]],
2247 "permutation: value: cannot have repeated values");
2248 vis[vec_[i]] = true;
2249 }
2250 }
2251 value(const std::initializer_list<int> &il)
2252 : value(std::vector<int>(il)) {}
2253
2254 // Fetches size.
2255 int size() const { return vec_.size(); }
2256
2257 // Fetches position idx.
2258 const int &operator[](int idx) const {
2259 tgen_ensure(0 <= idx and idx < size(),
2260 "permutation: value: index out of bounds");
2261 return vec_[idx];
2262 }
2263
2264 // Returns parity of the permutation (+1 if even, -1 if odd).
2265 // O(n).
2266 int parity() const {
2267 std::vector<bool> vis(size(), false);
2268 int cycles = 0;
2269
2270 for (int i = 0; i < size(); ++i)
2271 if (!vis[i]) {
2272 ++cycles;
2273 for (int j = i; !vis[j]; j = vec_[j])
2274 vis[j] = true;
2275 }
2276 // Even iff (n - cycles) is even.
2277 return ((size() - cycles) % 2 == 0) ? +1 : -1;
2278 }
2279
2280 // Sorts values in increasing order.
2281 // O(n).
2283 for (int i = 0; i < size(); ++i)
2284 vec_[i] = i;
2285 return *this;
2286 }
2287
2288 // Reverses permutation.
2289 // O(n).
2291 std::reverse(vec_.begin(), vec_.end());
2292 return *this;
2293 }
2294
2295 // Inverse of the permutation.
2296 // O(n).
2298 std::vector<int> inv(size());
2299 for (int i = 0; i < size(); ++i)
2300 inv[vec_[i]] = i;
2301 swap(vec_, inv);
2302 return *this;
2303 }
2304
2305 // Sets the separator, for printing.
2306 // O(1).
2307 value &separator(char sep) {
2308 sep_ = sep;
2309 return *this;
2310 }
2311
2312 // Sets that should print values 1-based.
2313 // O(1).
2315 add_1_ = true;
2316 return *this;
2317 }
2318
2319 // Shuffles permutation uniformly.
2320 // O(n).
2322 for (int i = 0; i < size(); ++i)
2323 std::swap(vec_[i], vec_[next(0, size() - 1)]);
2324 return *this;
2325 }
2326
2327 // Returns a random element uniformly.
2328 // O(1).
2329 int pick() const { return vec_[next<int>(0, size() - 1)]; }
2330
2331 // Returns vec_[i] with probability proportional to distribution[i].
2332 // O(1).
2333 template <typename Dist>
2334 int pick_by_distribution(const std::vector<Dist> &distribution) const {
2335 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
2336 "value and distribution must have the same size");
2337 return vec_[next_by_distribution(distribution)];
2338 }
2339 template <typename Dist>
2340 int pick_by_distribution(
2341 const std::initializer_list<Dist> &distribution) const {
2342 return pick_by_distribution(std::vector<Dist>(distribution));
2343 }
2344
2345 // Prints to std::ostream, separated by sep_.
2346 friend std::ostream &operator<<(std::ostream &out, const value &val) {
2347 for (int i = 0; i < val.size(); ++i) {
2348 if (i > 0)
2349 out << val.sep_;
2350 out << val[i] + val.add_1_;
2351 }
2352 return out;
2353 }
2354
2355 // Gets a std::vector representing the value.
2356 std::vector<int> to_std() const { return std_type(vec_); }
2357 };
2358
2359 // Generates permutation value.
2360 // O(n).
2361 value gen() const {
2362 if (!cycle_sizes_) {
2363 // Cycle sizes not specified.
2364 std::vector<int> idx_to_val(size_, -1), val_to_idx(size_, -1);
2365 for (auto [idx, val] : defs_) {
2367 0 <= val and val < size_,
2368 "permutation: value in permutation must be in [0, " +
2369 std::to_string(size_) + ")");
2370
2371 if (idx_to_val[idx] != -1) {
2372 tgen_ensure(idx_to_val[idx] == val,
2373 "permutation: cannot set an index to two "
2374 "different values");
2375 } else
2376 idx_to_val[idx] = val;
2377
2378 if (val_to_idx[val] != -1) {
2379 tgen_ensure(val_to_idx[val] == idx,
2380 "permutation: cannot set two indices to the "
2381 "same value");
2382 } else
2383 val_to_idx[val] = idx;
2384 }
2385
2386 std::vector<int> perm(size_);
2387 std::iota(perm.begin(), perm.end(), 0);
2388 shuffle(perm.begin(), perm.end());
2389 int cur_idx = 0;
2390 for (int &i : idx_to_val)
2391 if (i == -1) {
2392 // While this value is used, skip.
2393 while (val_to_idx[perm[cur_idx]] != -1)
2394 ++cur_idx;
2395 i = perm[cur_idx++];
2396 }
2397 return idx_to_val;
2398 }
2399
2400 // Creates cycles.
2401 std::vector<int> order(size_);
2402 std::iota(order.begin(), order.end(), 0);
2403 shuffle(order.begin(), order.end());
2404 int idx = 0;
2405 std::vector<std::vector<int>> cycles;
2406 for (int cycle_size : *cycle_sizes_) {
2407 cycles.emplace_back();
2408 for (int i = 0; i < cycle_size; ++i)
2409 cycles.back().push_back(order[idx++]);
2410 }
2411
2412 // Retrieves permutation from cycles.
2413 std::vector<int> perm(size_, -1);
2414 for (const std::vector<int> &cycle : cycles) {
2415 int cur_size = cycle.size();
2416 for (int i = 0; i < cur_size; ++i)
2417 perm[cycle[i]] = cycle[(i + 1) % cur_size];
2418 }
2419
2420 return value(perm);
2421 }
2422};
2423
2424/************
2425 * *
2426 * MATH *
2427 * *
2428 ************/
2429
2430namespace math {
2431
2432namespace detail {
2433
2434using namespace tgen::detail;
2435
2436inline int popcount(uint64_t x) { return __builtin_popcountll(x); }
2437
2438inline int ctzll(uint64_t x) {
2439 // Mystery code found on the internet.
2440 // Uses de Bruijn sequence.
2441 static const unsigned char index64[64] = {
2442 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
2443 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
2444 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
2445 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12};
2446 return index64[((x & -x) * 0x022FDD63CC95386D) >> 58];
2447}
2448
2449inline uint64_t mul_mod(uint64_t a, uint64_t b, uint64_t m) {
2450 return static_cast<u128>(a) * b % m;
2451}
2452
2453// O(log n).
2454// 0 <= x < m.
2455inline uint64_t expo_mod(uint64_t x, uint64_t y, uint64_t m) {
2456 if (!y)
2457 return 1;
2458 uint64_t ans = expo_mod(mul_mod(x, x, m), y / 2, m);
2459 return y % 2 ? mul_mod(x, ans, m) : ans;
2460}
2461
2462} // namespace detail
2463
2464// O(log^2 n).
2465inline bool is_prime(uint64_t n) {
2466 if (n < 2)
2467 return false;
2468 if (n == 2 or n == 3)
2469 return true;
2470 if (n % 2 == 0)
2471 return false;
2472
2473 uint64_t r = detail::ctzll(n - 1), d = n >> r;
2474 // These bases are guaranteed to work for n <= 2^64.
2475 for (int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
2476 uint64_t x = detail::expo_mod(a, d, n);
2477 if (x == 1 or x == n - 1 or a % n == 0)
2478 continue;
2479
2480 for (uint64_t j = 0; j < r - 1; ++j) {
2481 x = detail::mul_mod(x, x, n);
2482 if (x == n - 1)
2483 break;
2484 }
2485 if (x != n - 1)
2486 return false;
2487 }
2488 return true;
2489}
2490
2491namespace detail {
2492
2493inline uint64_t pollard_rho(uint64_t n) {
2494 if (n == 1 or is_prime(n))
2495 return n;
2496 auto f = [n](uint64_t x) { return mul_mod(x, x, n) + 1; };
2497
2498 uint64_t x = 0, y = 0, t = 30, prd = 2, x0 = 1, q;
2499 while (t % 40 != 0 or std::gcd(prd, n) == 1) {
2500 if (x == y)
2501 x = ++x0, y = f(x);
2502 q = mul_mod(prd, x > y ? x - y : y - x, n);
2503 if (q != 0)
2504 prd = q;
2505 x = f(x), y = f(f(y)), ++t;
2506 }
2507 return std::gcd(prd, n);
2508}
2509
2510inline std::vector<uint64_t> factor(uint64_t n) {
2511 if (n == 1)
2512 return {};
2513 if (is_prime(n))
2514 return {n};
2515 uint64_t d = pollard_rho(n);
2516 std::vector<uint64_t> l = factor(d), r = factor(n / d);
2517 l.insert(l.end(), r.begin(), r.end());
2518 return l;
2519}
2520
2521// Error handling.
2522template <typename T>
2523std::runtime_error there_is_no_in_range_error(const std::string &type, T l,
2524 T r) {
2525 return error("math: there is no " + type + " in range [" +
2526 std::to_string(l) + ", " + std::to_string(r) + "]");
2527}
2528template <typename T>
2529std::runtime_error there_is_no_from_error(const std::string &type, T r) {
2530 return error("math: there is no " + type + " from " + std::to_string(r));
2531}
2532template <typename T>
2533std::runtime_error there_is_no_upto_error(const std::string &type, T r) {
2534 return error("math: there is no " + type + " up to " + std::to_string(r));
2535}
2536
2537// O(log mod).
2538// 0 < a < mod.
2539// gcd(a, mod) = 1.
2540inline i128 modular_inverse_128(i128 a, i128 mod) {
2541 tgen_ensure(0 < a and a < mod,
2542 "math: modular inverse requires 0 < value < mod");
2543
2544 i128 t = 0, new_t = 1;
2545 i128 r = mod, new_r = a;
2546
2547 while (new_r != 0) {
2548 i128 q = r / new_r;
2549
2550 auto tmp_t = t - q * new_t;
2551 t = new_t;
2552 new_t = tmp_t;
2553
2554 auto tmp_r = r - q * new_r;
2555 r = new_r;
2556 new_r = tmp_r;
2557 }
2558
2559 tgen_ensure(r == 1, "math: remainder and mod must be coprime");
2560
2561 if (t < 0)
2562 t += mod;
2563 return t;
2564}
2565
2566// checks if a * b <= limit, for positive numbers.
2567inline bool mul_leq(uint64_t a, uint64_t b, uint64_t limit) {
2568 if (a == 0 or b == 0)
2569 return true;
2570 return a <= limit / b;
2571}
2572
2573// base^exp, or null if base^exp > limit.
2574inline std::optional<uint64_t> expo(uint64_t base, uint64_t exp,
2575 uint64_t limit) {
2576 uint64_t result = 1;
2577
2578 while (exp) {
2579 if (exp & 1) {
2580 if (!mul_leq(result, base, limit))
2581 return std::nullopt;
2582 result *= base;
2583 }
2584
2585 exp >>= 1;
2586 // Necessary for correctness.
2587 if (!exp)
2588 break;
2589
2590 if (!mul_leq(base, base, limit))
2591 return std::nullopt;
2592 base *= base;
2593 }
2594 return result;
2595}
2596
2597// O(log n log k).
2598// 0 < k.
2599inline uint64_t kth_root_floor(uint64_t n, uint64_t k) {
2600 tgen_ensure_against_bug(k > 0, "math: value must be valid");
2601 if (k == 1 or n <= 1)
2602 return n;
2603
2604 uint64_t lo = 1, hi = 1ULL << ((64 + k - 1) / k);
2605
2606 while (lo < hi) {
2607 uint64_t mid = lo + (hi - lo + 1) / 2;
2608
2609 if (expo(mid, k, n)) {
2610 lo = mid;
2611 } else {
2612 hi = mid - 1;
2613 }
2614 }
2615 return lo;
2616}
2617
2618// gcd(a, b).
2619// O(log a).
2620inline i128 gcd128(i128 a, i128 b) {
2621 if (a < 0)
2622 a = -a;
2623 if (b < 0)
2624 b = -b;
2625 while (b != 0) {
2626 i128 t = a % b;
2627 a = b;
2628 b = t;
2629 }
2630 return a;
2631}
2632
2633// min(2^64, a*b).
2634// O(log a).
2635// a, b >= 0.
2636inline i128 mul_saturate(i128 a, i128 b) {
2637 tgen_ensure(a >= 0 and b >= 0);
2638 static const i128 LIMIT = static_cast<i128>(1) << 64;
2639 if (a == 0 or b == 0)
2640 return 0;
2641 if (a > LIMIT / b)
2642 return LIMIT;
2643 return a * b;
2644}
2645
2646struct crt {
2647 using T = i128;
2648 T a, m;
2649
2650 crt() : a(0), m(1) {}
2651 crt(T a_, T m_) : a(a_), m(m_) {}
2652 crt operator*(crt C) {
2653 if (m == 0 or C.m == 0)
2654 return {-1, 0};
2655
2656 T g = gcd128(m, C.m);
2657 if ((C.a - a) % g != 0)
2658 return {-1, 0};
2659
2660 T m1 = m / g;
2661 T m2 = C.m / g;
2662
2663 if (m2 == 1)
2664 return {a, m};
2665
2666 T inv = modular_inverse_128(m1 % m2, m2);
2667
2668 T k = ((C.a - a) / g) % m2;
2669 if (k < 0)
2670 k += m2;
2671
2672 k = static_cast<u128>(k) * inv % m2;
2673
2674 T lcm = mul_saturate(m, m2);
2675
2676 T res = (a + static_cast<T>((static_cast<u128>(k) * m) % lcm)) % lcm;
2677 if (res < 0)
2678 res += lcm;
2679
2680 return {res, lcm};
2681 }
2682};
2683
2684// Math hacks to operate on log space.
2685
2686inline constexpr long double LOG_ZERO = -INFINITY;
2687inline constexpr long double LOG_ONE = 0.0;
2688
2689inline long double log_space(long double x) {
2690 return x == 0.0 ? LOG_ZERO : std::log(x);
2691}
2692
2693// Math hack to add two values in log space.
2694inline long double add_log_space(long double a, long double b) {
2695 if (a < b)
2696 std::swap(a, b);
2697 if (b == LOG_ZERO)
2698 return a;
2699 return a + log1p(exp(b - a));
2700}
2701
2702// Math hack to subtract two values in log space.
2703// a >= b.
2704inline long double sub_log_space(long double a, long double b) {
2705 if (b >= a)
2706 return LOG_ZERO;
2707 if (b == LOG_ZERO)
2708 return a;
2709 return a + log1p(-exp(b - a));
2710}
2711
2712} // namespace detail
2713
2714// Sorted.
2715// O(n^(1/4) log n) expected.
2716// 0 < n.
2717inline std::vector<uint64_t> factor(uint64_t n) {
2718 tgen_ensure(n > 0, "math: number to factor must be positive");
2719 auto factors = detail::factor(n);
2720 std::sort(factors.begin(), factors.end());
2721 return factors;
2722}
2723
2724// Sorted.
2725// O(n^(1/4) log n) expected.
2726// 0 < n.
2727inline std::vector<std::pair<uint64_t, int>> factor_by_prime(uint64_t n) {
2728 tgen_ensure(n > 0, "math: number to factor must be positive");
2729 std::vector<std::pair<uint64_t, int>> primes;
2730 for (uint64_t p : factor(n)) {
2731 if (!primes.empty() and primes.back().first == p)
2732 ++primes.back().second;
2733 else
2734 primes.emplace_back(p, 1);
2735 }
2736 return primes;
2737}
2738
2739// O(log mod).
2740// 0 < a < mod.
2741// gcd(a, mod) = 1.
2742inline uint64_t modular_inverse(uint64_t a, uint64_t mod) {
2743 return detail::modular_inverse_128(a, mod);
2744}
2745
2746// O(n^(1/4) log n) expected.
2747// 0 < n.
2748inline uint64_t totient(uint64_t n) {
2749 tgen_ensure(n > 0, "math: totient(0) is undefined");
2750 uint64_t phi = n;
2751
2752 for (auto [p, e] : factor_by_prime(n))
2753 phi -= phi / p;
2754
2755 return phi;
2756}
2757
2758// Returns `(p_i, g_i)`: `p_i` is the prime, `g_i` is the gap.
2759inline const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> &
2760prime_gaps() {
2761 // From https://en.wikipedia.org/wiki/Prime_gap.
2762 static const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> value{
2763 /* clang-format off */ {
2764 2, 3, 7, 23, 89, 113, 523, 887, 1129, 1327, 9551, 15683, 19609,
2765 31397, 155921, 360653, 370261, 492113, 1349533, 1357201, 2010733,
2766 4652353, 17051707, 20831323, 47326693, 122164747, 189695659,
2767 191912783, 387096133, 436273009, 1294268491, 1453168141,
2768 2300942549, 3842610773, 4302407359, 10726904659, 20678048297,
2769 22367084959, 25056082087, 42652618343, 127976334671, 182226896239,
2770 241160624143, 297501075799, 303371455241, 304599508537,
2771 416608695821, 461690510011, 614487453523, 738832927927,
2772 1346294310749, 1408695493609, 1968188556461, 2614941710599,
2773 7177162611713, 13829048559701, 19581334192423, 42842283925351,
2774 90874329411493, 171231342420521, 218209405436543, 1189459969825483,
2775 1686994940955803, 1693182318746371, 43841547845541059,
2776 55350776431903243, 80873624627234849, 203986478517455989,
2777 218034721194214273, 305405826521087869, 352521223451364323,
2778 401429925999153707, 418032645936712127, 804212830686677669,
2779 1425172824437699411, 5733241593241196731, 6787988999657777797
2780 }, /* clang-format on */
2781 {1, 2, 4, 6, 8, 14, 18, 20, 22, 34, 36,
2782 44, 52, 72, 86, 96, 112, 114, 118, 132, 148, 154,
2783 180, 210, 220, 222, 234, 248, 250, 282, 288, 292, 320,
2784 336, 354, 382, 384, 394, 456, 464, 468, 474, 486, 490,
2785 500, 514, 516, 532, 534, 540, 582, 588, 602, 652, 674,
2786 716, 766, 778, 804, 806, 906, 916, 924, 1132, 1184, 1198,
2787 1220, 1224, 1248, 1272, 1328, 1356, 1370, 1442, 1476, 1488, 1510}};
2788
2789 return value;
2790}
2791
2792// Returns pair (first_composite_in_gap, last_composite_in_gap).
2793// O(log(right)) approximately.
2794inline std::pair<uint64_t, uint64_t> prime_gap_upto(uint64_t right) {
2795 if (right < 4)
2796 throw detail::there_is_no_upto_error("prime gap", right);
2797
2798 const auto &[P, G] = prime_gaps();
2799 for (int i = P.size() - 1;; --i) {
2800 if (P[i] >= right)
2801 continue;
2802
2803 uint64_t real_right = std::min(right, P[i] + G[i] - 1);
2804 uint64_t prev = i > 0 ? G[i - 1] : 0;
2805 uint64_t curr = real_right - P[i];
2806
2807 if (curr >= prev)
2808 return {P[i] + 1, real_right};
2809 }
2810}
2811
2812// From https://oeis.org/A002182/b002182.txt.
2814 /* clang-format off */
2815 static const std::vector<uint64_t> highly_composites = {
2816 1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680,
2817 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440,
2818 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280,
2819 720720, 1081080, 1441440, 2162160, 2882880, 3603600, 4324320, 6486480,
2820 7207200, 8648640, 10810800, 14414400, 17297280, 21621600, 32432400,
2821 36756720, 43243200, 61261200, 73513440, 110270160, 122522400, 147026880,
2822 183783600, 245044800, 294053760, 367567200, 551350800, 698377680, 735134400,
2823 1102701600, 1396755360, 2095133040, 2205403200, 2327925600, 2793510720,
2824 3491888400, 4655851200, 5587021440, 6983776800, 10475665200, 13967553600,
2825 20951330400, 27935107200, 41902660800, 48886437600, 64250746560,
2826 73329656400, 80313433200, 97772875200, 128501493120, 146659312800,
2827 160626866400, 240940299600, 293318625600, 321253732800, 481880599200,
2828 642507465600, 963761198400, 1124388064800, 1606268664000, 1686582097200,
2829 1927522396800, 2248776129600, 3212537328000, 3373164194400, 4497552259200,
2830 6746328388800, 8995104518400, 9316358251200, 13492656777600, 18632716502400,
2831 26985313555200, 27949074753600, 32607253879200, 46581791256000,
2832 48910880818800, 55898149507200, 65214507758400, 93163582512000,
2833 97821761637600, 130429015516800, 195643523275200, 260858031033600,
2834 288807105787200, 391287046550400, 577614211574400, 782574093100800,
2835 866421317361600, 1010824870255200, 1444035528936000, 1516237305382800,
2836 1732842634723200, 2021649740510400, 2888071057872000, 3032474610765600,
2837 4043299481020800, 6064949221531200, 8086598962041600, 10108248702552000,
2838 12129898443062400, 18194847664593600, 20216497405104000, 24259796886124800,
2839 30324746107656000, 36389695329187200, 48519593772249600, 60649492215312000,
2840 72779390658374400, 74801040398884800, 106858629141264000,
2841 112201560598327200, 149602080797769600, 224403121196654400,
2842 299204161595539200, 374005201994424000, 448806242393308800,
2843 673209363589963200, 748010403988848000, 897612484786617600,
2844 1122015605983272000, 1346418727179926400, 1795224969573235200,
2845 2244031211966544000, 2692837454359852800, 3066842656354276800,
2846 4381203794791824000, 4488062423933088000, 6133685312708553600,
2847 8976124847866176000, 9200527969062830400, 12267370625417107200ULL,
2848 15334213281771384000ULL, 18401055938125660800ULL}; /* clang-format on */
2849 return highly_composites;
2850}
2851
2852// O(log(right)) approximately.
2853inline uint64_t highly_composite_upto(uint64_t right) {
2854 for (int i = highly_composites().size() - 1; i >= 0; --i)
2855 if (highly_composites()[i] <= right)
2856 return highly_composites()[i];
2857
2858 throw detail::there_is_no_upto_error("highly composite number", right);
2859}
2860
2861// O(log^3 (right)) expected.
2862// Generates a random prime in [left, right].
2863inline uint64_t gen_prime(uint64_t left, uint64_t right) {
2864 if (right < left or right < 2)
2865 throw detail::there_is_no_in_range_error("prime", left, right);
2866 left = std::max<uint64_t>(left, 2);
2867 auto [l_gap, r_gap] = prime_gap_upto(right);
2868 if (right - left + 1 <= r_gap - l_gap + 1) {
2869 // There might be no primes in the range.
2870 std::vector<uint64_t> vals(right - left + 1);
2871 iota(vals.begin(), vals.end(), left);
2872 shuffle(vals.begin(), vals.end());
2873 for (uint64_t i : vals)
2874 if (is_prime(i))
2875 return i;
2876 throw detail::there_is_no_in_range_error("prime", left, right);
2877 }
2878
2879 uint64_t n;
2880 do {
2881 n = next(left, right);
2882 } while (!is_prime(n));
2883 return n;
2884}
2885
2886// O(log^3 (left)) expected.
2887// left <= 2^64 - 59.
2888inline uint64_t prime_from(uint64_t left) {
2889 tgen_ensure(left <= std::numeric_limits<uint64_t>::max() - 58,
2890 "math: invalid bound");
2891 for (uint64_t i = std::max<uint64_t>(2, left);; ++i)
2892 if (is_prime(i))
2893 return i;
2894}
2895
2896// O(log^3 (right)) expected.
2897inline uint64_t prime_upto(uint64_t right) {
2898 if (right >= 2)
2899 for (uint64_t i = right; i >= 2; --i)
2900 if (is_prime(i))
2901 return i;
2902 throw detail::there_is_no_upto_error("prime", right);
2903}
2904
2905// O(n^(1/4) log n) expected.
2906// 0 < n.
2907inline int num_divisors(uint64_t n) {
2908 int divisors = 1;
2909 for (auto [p, e] : factor_by_prime(n))
2910 divisors *= (e + 1);
2911 return divisors;
2912}
2913
2914// Random number in [left, right] with `divisor_count` divisors.
2915// O(log(right) log(divisor_count)).
2916// divisor_count must be prime.
2917inline uint64_t gen_divisor_count(uint64_t left, uint64_t right,
2918 int divisor_count) {
2919 tgen_ensure(divisor_count > 0 and is_prime(divisor_count),
2920 "math: divisor count must be prime");
2921 int root = divisor_count - 1;
2922 uint64_t lo = detail::kth_root_floor(left, root);
2923 if (*detail::expo(lo, root, left) < left)
2924 ++lo;
2925 uint64_t p = gen_prime(lo, detail::kth_root_floor(right, root));
2926 return *detail::expo(p, root, right);
2927}
2928
2929// O(|mods| + log (right)).
2930// |rems| = |mods|.
2931// rems_i < mods_i.
2932inline uint64_t gen_congruent(uint64_t left, uint64_t right,
2933 std::vector<uint64_t> rems,
2934 std::vector<uint64_t> mods) {
2935 if (left > right)
2936 throw detail::there_is_no_in_range_error("congruent number", left,
2937 right);
2938 tgen_ensure(rems.size() == mods.size(),
2939 "math: number of remainders and mods must be the same");
2940 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
2941
2942 detail::crt crt;
2943 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
2944 tgen_ensure(rems[i] < mods[i],
2945 "math: remainder must be smaller than the mod");
2946 crt = crt * detail::crt(rems[i], mods[i]);
2947
2948 if (crt.a == -1)
2949 throw detail::there_is_no_in_range_error("congruent number", left,
2950 right);
2951 if (crt.m > right) {
2952 if (!(left <= crt.a and crt.a <= right))
2953 throw detail::there_is_no_in_range_error("congruent number",
2954 left, right);
2955
2956 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
2957 if (crt.a % mods[j] != rems[j])
2958 throw detail::there_is_no_in_range_error("congruent number",
2959 left, right);
2960 return crt.a;
2961 }
2962 }
2963
2964 uint64_t k_min = crt.a >= left ? 0 : ((left - crt.a) + crt.m - 1) / crt.m;
2965 uint64_t k_max = (right - crt.a) / crt.m;
2966
2967 if (k_min > k_max)
2968 throw detail::there_is_no_in_range_error("congruent number", left,
2969 right);
2970
2971 return crt.a + next(k_min, k_max) * crt.m;
2972}
2973
2974// O(log (right)).
2975// rem < mod.
2976inline uint64_t gen_congruent(uint64_t left, uint64_t right, uint64_t rem,
2977 uint64_t mod) {
2978 return gen_congruent(left, right, std::vector<uint64_t>({rem}),
2979 std::vector<uint64_t>({mod}));
2980}
2981
2982// First congruent number >= left.
2983// O(|mods| + log (left)).
2984// |rems| = |mods|.
2985// rems_i < mods_i.
2986inline uint64_t congruent_from(uint64_t left, std::vector<uint64_t> rems,
2987 std::vector<uint64_t> mods) {
2988 tgen_ensure(rems.size() == mods.size(),
2989 "math: number of remainders and mods must be the same");
2990 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
2991
2992 detail::crt crt;
2993 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
2994 tgen_ensure(rems[i] < mods[i],
2995 "math: remainder must be smaller than the mod");
2996 crt = crt * detail::crt(rems[i], mods[i]);
2997
2998 if (crt.a == -1)
2999 throw detail::there_is_no_from_error("congruent number", left);
3000 if (crt.m > std::numeric_limits<uint64_t>::max()) {
3001 if (crt.a < left)
3002 throw detail::error(
3003 "math: congruent number does not exist or is too large");
3004
3005 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
3006 if (crt.a % mods[j] != rems[j])
3007 throw detail::error("math: congruent number does "
3008 "not exist or is too large");
3009 return crt.a;
3010 }
3011 }
3012
3013 uint64_t k = 0;
3014 if (crt.a < left)
3015 k = ((left - crt.a) + crt.m - 1) / crt.m;
3016 detail::i128 result = crt.a + k * crt.m;
3017
3018 if (result > std::numeric_limits<uint64_t>::max())
3019 throw detail::error("math: congruent number is too large");
3020 return result;
3021}
3022
3023// O(log (left))
3024// rem < mod.
3025inline uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod) {
3026 return congruent_from(left, std::vector<uint64_t>{rem},
3027 std::vector<uint64_t>{mod});
3028}
3029
3030// Last congruent number <= right.
3031// O(|mods| + log (right)).
3032// |rems| = |mods|.
3033// rems_i < mods_i.
3034inline uint64_t congruent_upto(uint64_t right, std::vector<uint64_t> rems,
3035 std::vector<uint64_t> mods) {
3036 tgen_ensure(rems.size() == mods.size(),
3037 "math: number of remainders and mods must be the same");
3038 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
3039
3040 detail::crt crt;
3041 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
3042 tgen_ensure(rems[i] < mods[i],
3043 "math: remainder must be smaller than the mod");
3044
3045 crt = crt * detail::crt(rems[i], mods[i]);
3046
3047 if (crt.a == -1)
3048 throw detail::there_is_no_upto_error("congruent number", right);
3049 if (crt.m > right) {
3050 if (!(crt.a <= right))
3051 throw detail::there_is_no_upto_error("congruent number", right);
3052
3053 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
3054 if (crt.a % mods[j] != rems[j])
3055 throw detail::there_is_no_upto_error("congruent number",
3056 right);
3057 return crt.a;
3058 }
3059 }
3060
3061 if (crt.a > right)
3062 throw detail::there_is_no_upto_error("congruent number", right);
3063
3064 uint64_t k = (right - crt.a) / crt.m;
3065 detail::i128 result = crt.a + k * crt.m;
3066
3067 if (result < 0)
3068 throw detail::there_is_no_upto_error("congruent number", right);
3069 return result;
3070}
3071
3072// O(log r)
3073// rem < mod.
3074inline uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod) {
3075 return congruent_upto(right, std::vector<uint64_t>{rem},
3076 std::vector<uint64_t>{mod});
3077}
3078
3079// Mod used for FFT/NTT.
3080inline constexpr int FFT_MOD = 998244353;
3081
3082// Fibonacci sequence up to 2^64.
3083inline const std::vector<uint64_t> &fibonacci() {
3084 static const std::vector<uint64_t> fib = [] {
3085 std::vector<uint64_t> v = {0, 1};
3086 while (v.back() <=
3087 std::numeric_limits<uint64_t>::max() - v[v.size() - 2])
3088 v.push_back(v.back() + v[v.size() - 2]);
3089 return v;
3090 }();
3091 return fib;
3092}
3093
3094// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3095// O(n).
3096// 0 < n.
3097// 0 < part_left.
3098inline std::vector<int>
3099gen_partition(int n, int part_left = 1,
3100 std::optional<int> part_right = std::nullopt) {
3101 if (!part_right.has_value())
3102 part_right = n;
3103 part_right = std::min(*part_right, n);
3104 tgen_ensure(n > 0 and part_left > 0,
3105 "math: invalid parameters to gen_partition");
3106 tgen_ensure(part_left <= n and *part_right > 0, "math: no such partition");
3107
3108 // dp[i] = log(number of ways to add to i).
3109 std::vector<long double> dp(n + 1, detail::LOG_ZERO);
3110 dp[0] = detail::LOG_ONE;
3111 long double window = detail::LOG_ZERO;
3112 for (int i = 1; i <= n; ++i) {
3113 if (i >= part_left)
3114 window = detail::add_log_space(window, dp[i - part_left]);
3115 if (i >= *part_right + 1)
3116 window = detail::sub_log_space(window, dp[i - *part_right - 1]);
3117 dp[i] = window;
3118 }
3119 tgen_ensure(dp[n] >= 0, "math: no such partition");
3120
3121 // Crazy math tricks ahead.
3122 auto dp_pref = dp;
3123 for (int i = 1; i <= n; ++i)
3124 dp_pref[i] = detail::add_log_space(dp_pref[i - 1], dp[i]);
3125
3126 std::vector<int> part;
3127 int sum = n;
3128 while (sum > 0) {
3129 // Will generate a number such that what remains is in [l, r].
3130 int l = std::max(0, sum - *part_right), r = sum - part_left;
3131 detail::tgen_ensure_against_bug(r >= 0, "math: r < 0 in gen_partition");
3132
3133 int nxt_sum = std::min(sum, r);
3134 long double random = next<long double>(0, 1);
3135
3136 // We generate a value X (log space), and then choose nxt_sum such
3137 // that dp_pref[nxt_sum-1] < X <= dp_pref[nxt_sum].
3138
3139 // Math hack:
3140 // Let A = pref[l-1], B = pref[r], U = rand().
3141 // X = log[exp(A) + U * (exp(B) - exp(A))]
3142 // = log{exp(B) * [exp(A) / exp(B) + U * (1 - exp(A) / exp(B))]}
3143 // = B + log[exp(A - B) + U - U * exp(A - B))]
3144 // = B + log[U + (1 - U) * exp(A - B)].
3145 long double val_l = l ? dp_pref[l - 1] : detail::LOG_ZERO,
3146 val_r = dp_pref[r];
3147 while (nxt_sum > l and
3148 dp_pref[nxt_sum - 1] >=
3149 val_r + detail::log_space(random +
3150 (1 - random) * exp(val_l - val_r)))
3151 --nxt_sum;
3152
3153 part.push_back(sum - nxt_sum);
3154 sum = nxt_sum;
3155 }
3156
3157 return part;
3158}
3159
3160// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3161// O(n) time/memory if part_right is not set, O(n * k) time/memory otherwise.
3162// 0 < k <= n.
3163// 0 <= part_left.
3164inline std::vector<int>
3165gen_partition_fixed_size(int n, int k, int part_left = 0,
3166 std::optional<int> part_right = std::nullopt) {
3167 if (!part_right.has_value())
3168 part_right = n;
3169 part_right = std::min(*part_right, n);
3170 tgen_ensure(0 < k and k <= n and part_left >= 0,
3171 "math: invalid parameters to gen_partition_fixed_size");
3172 tgen_ensure(static_cast<long long>(k) * part_left <= n and
3173 n <= static_cast<long long>(k) * (*part_right),
3174 "math: no such partition");
3175
3176 // What we need to distribute to the parts.
3177 int s = n - k * part_left;
3178
3179 std::vector<int> part(k);
3180 if (*part_right == n) {
3181 // Stars and bars - O(n).
3182 std::vector<int> cuts = {-1};
3183
3184 int total = s + k - 1, bars = k - 1;
3185 for (int i = 0; i < total and bars > 0; ++i)
3186 if (next<long double>(0, 1) <
3187 static_cast<long double>(bars) / (total - i)) {
3188 cuts.push_back(i);
3189 --bars;
3190 }
3191 cuts.push_back(total);
3192
3193 // Recovers parts.
3194 for (int i = 0; i < k; ++i)
3195 part[i] = cuts[i + 1] - cuts[i] - 1;
3196 } else {
3197 // DP with log trick - O(nk).
3198 int u = *part_right - part_left;
3199
3200 // dp[i][j] = log(#ways to fill i parts with sum j)
3201 std::vector<std::vector<long double>> dp(
3202 k + 1, std::vector<long double>(s + 1, detail::LOG_ZERO));
3203 dp[0][0] = detail::LOG_ONE;
3204
3205 for (int i = 1; i <= k; ++i) {
3206 std::vector<long double> pref = dp[i - 1];
3207 for (int j = 1; j <= s; ++j)
3208 pref[j] = detail::add_log_space(pref[j - 1], dp[i - 1][j]);
3209
3210 for (int j = 0; j <= s; ++j) {
3211 dp[i][j] = pref[j];
3212 if (j >= u + 1)
3213 dp[i][j] = detail::sub_log_space(dp[i][j], pref[j - u - 1]);
3214 }
3215 }
3216
3217 // Recovers parts backwards.
3218 int left_to_distribute = s;
3219 for (int i = k; i >= 1; --i) {
3220 long double log_total = detail::LOG_ZERO;
3221 for (int j = 0; j <= u and j <= left_to_distribute; ++j)
3222 log_total = detail::add_log_space(
3223 log_total, dp[i - 1][left_to_distribute - j]);
3224 detail::tgen_ensure_against_bug(
3225 log_total != detail::LOG_ZERO,
3226 "math: total == 0 in gen_partition_fixed_size");
3227
3228 // Now we choose a number with probability proportional to
3229 // dp[i-1][.].
3230
3231 // log(rand() * total) = log(rand()) + log(total).
3232 long double random =
3233 detail::log_space(next<long double>(0, 1)) + log_total;
3234
3235 long double cur_prob = detail::LOG_ZERO;
3236 int chosen = 0;
3237 for (int j = 0; j <= u and j <= left_to_distribute; ++j) {
3238 cur_prob = detail::add_log_space(
3239 cur_prob, dp[i - 1][left_to_distribute - j]);
3240 if (random < cur_prob) {
3241 chosen = j;
3242 break;
3243 }
3244 }
3245
3246 part[k - i] = chosen;
3247 left_to_distribute -= chosen;
3248 }
3249 }
3250
3251 for (int &i : part)
3252 i += part_left;
3253 return part;
3254}
3255
3256// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3257// Inspired by jngen rndm.partition: random delimiters, sort, gap recovery;
3258// omits jngen's part reordering, shuffles, and two-pass redistribution.
3259// 0 < k <= n.
3260// 0 <= part_left.
3261// Not uniformly random; optimized for speed.
3262// O(k log k).
3264 uint64_t n, int k, uint64_t part_left = 0,
3265 std::optional<uint64_t> part_right = std::nullopt) {
3266 if (!part_right.has_value())
3267 part_right = n;
3268 part_right = std::min(*part_right, n);
3269
3270 detail::u128 n128 = n;
3271 detail::u128 k128 = k;
3272 detail::u128 part_left128 = part_left;
3273 detail::u128 part_right128 = *part_right;
3274
3275 tgen_ensure(k > 0 and k128 <= n128,
3276 "math: invalid parameters to gen_partition_fixed_size_fast");
3277 tgen_ensure(part_right128 >= part_left128 and
3278 k128 * part_left128 <= n128 and
3279 k128 * part_right128 >= n128,
3280 "math: no such partition");
3281
3282 uint64_t slack_total = n128 - k128 * part_left128;
3283 uint64_t slack_max = part_right128 - part_left128;
3284
3285 std::vector<uint64_t> part(k);
3286 if (k == 1) {
3287 part[0] = slack_total;
3288 } else {
3289 std::vector<uint64_t> cuts(k - 1);
3290 for (uint64_t &d : cuts)
3291 d = next<uint64_t>(0, slack_total);
3292 std::sort(cuts.begin(), cuts.end());
3293
3294 uint64_t prev = 0;
3295 for (int i = 0; i + 1 < k; ++i) {
3296 part[i] = cuts[i] - prev;
3297 prev = cuts[i];
3298 }
3299 part[k - 1] = slack_total - prev;
3300 }
3301
3302 auto add_part_left = [part_left](uint64_t x) -> uint64_t {
3303 detail::u128 val = x + part_left;
3304 detail::tgen_ensure_against_bug(
3305 val <= std::numeric_limits<uint64_t>::max(),
3306 "math: part + part_left exceeds uint64_t in "
3307 "gen_partition_fixed_size_fast");
3308 return val;
3309 };
3310
3311 if (slack_max >= slack_total) {
3312 for (uint64_t &x : part)
3313 x = add_part_left(x);
3314 return part;
3315 }
3316
3317 detail::u128 remaining = 0;
3318 for (uint64_t &x : part) {
3319 if (x > slack_max) {
3320 remaining += x - slack_max;
3321 x = slack_max;
3322 }
3323 x = add_part_left(x);
3324 }
3325
3326 if (remaining > 0) {
3327 for (uint64_t &x : part) {
3328 if (x < *part_right && remaining > 0) {
3329 detail::u128 room = *part_right - x;
3330 detail::u128 add = std::min(remaining, room);
3331 detail::u128 val = x + add;
3332 detail::tgen_ensure_against_bug(
3333 val <= *part_right,
3334 "math: part exceeds part_right after redistribution in "
3335 "gen_partition_fixed_size_fast");
3336 x = val;
3337 remaining -= add;
3338 }
3339 }
3340 detail::tgen_ensure_against_bug(
3341 remaining == 0, "math: remaining mass after redistribution in "
3342 "gen_partition_fixed_size_fast");
3343 }
3344
3345 return part;
3346}
3347
3348// Random partition of elements into k ordered groups (input order preserved).
3349// If max_size is unset, part sizes are uniform via gen_partition_fixed_size.
3350// If max_size is set, uses gen_partition_fixed_size_fast (not uniform).
3351// O(n) if max_size is unset; O(n + k log k) if max_size is set.
3352template <typename T>
3353std::vector<std::vector<T>>
3354partition_elements(std::vector<T> elements, int k, int min_size = 0,
3355 std::optional<uint64_t> max_size = std::nullopt) {
3356 size_t n = elements.size();
3357 tgen_ensure(k > 0, "math: partition_elements: k must be positive");
3358 tgen_ensure(min_size >= 0,
3359 "math: partition_elements: min_size must be non-negative");
3360
3361 std::vector<uint64_t> sizes;
3362 if (max_size.has_value()) {
3363 sizes = gen_partition_fixed_size_fast(n, k, min_size, max_size);
3364 } else {
3365 for (int sz : gen_partition_fixed_size(n, k, min_size))
3366 sizes.push_back(sz);
3367 }
3368
3369 std::vector<std::vector<T>> groups;
3370 groups.reserve(k);
3371 size_t pos = 0;
3372 for (uint64_t sz : sizes) {
3373 groups.emplace_back(elements.begin() + pos,
3374 elements.begin() + pos + sz);
3375 pos += sz;
3376 }
3377 return groups;
3378}
3379
3380}; // namespace math
3381
3382/**************
3383 * *
3384 * STRING *
3385 * *
3386 **************/
3387
3388namespace detail {
3389
3390/*
3391 * Regex.
3392 *
3393 * Compatible with testlib's regex.
3394 *
3395 * Operations:
3396 * - A single character yields itself ("a", "3").
3397 * - A list of characters inside square braces yields any a random element
3398 * from the list ("[abc123]").
3399 * - A range of characters is equivalent to listing them ("[a-z1-9A-Z]").
3400 * - A pattern followed by {n} yields the pattern repeated n times ("a{3}").
3401 * - A pattern followed by {l,r} yields the pattern repeated between l and r
3402 * times, uniformly at random ("a{3,5}").
3403 * - A list of patterns separated by | yields a random pattern from the
3404 * list, uniformly at random ("abc|def|ghi").
3405 * - Parentheses can be used for grouping ("a((a|b){3})").
3406 *
3407 * Examples:
3408 * 1. str("[1-9][0-9]{1,2}") generates two- or three-digit numbers.
3409 * 2. str("a[b-d]{2}|e") generates "e" or a random string of length 3, with
3410 * the first character being 'a' and the second and
3411 * third characters being 'b', 'c', or 'd'.
3412 * 3. str("[1-9][0-9]{%d}", n-1) generates n-digit numbers.
3413 *
3414 * Operations defined by {n} and {l,r} are applied from left to right, and
3415 * the pattern that comes before has its delimiters defined either by () or
3416 * [] at its end or is taken from the beginning of the pattern (in
3417 * "a[bc]{2}", "{2}" is applied to "[bc]", and in "[01]abc{3}", the "{3}" is
3418 * applied to "[01]abc").
3419 */
3420
3421// If it has children, it is either a SEQ or an OR group, defined by the
3422// pattern_ field.
3423struct regex_node {
3424 // Considered to be repetition of left_bound != -1, pattern if
3425 // children_.empty(), otherwise "SEQ" or "OR", defined by the pattern_
3426 // field.
3427 std::string
3428 pattern_; // Either pattern, or "SEQ" or "OR" (if !children_.empty()).
3429 std::vector<regex_node> children_; // Children, when SEQ or OR.
3430 int left_bound_, right_bound_; // Left and right bounds of the repetition,
3431 // or -1 if not a repetition.
3432 double
3433 log_space_num_ways_; // Log space number of ways to match the pattern.
3434 std::optional<distinct_container<char>>
3435 distinct_; // Distinct generator for the pattern, for [chars].
3436
3437 // c or [chars].
3438 regex_node(const std::string &pattern)
3439 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3440 if (pattern.size() == 1) {
3441 log_space_num_ways_ = math::detail::LOG_ONE;
3442 return;
3443 }
3444 tgen_ensure_against_bug(pattern[0] == '[' and pattern.back() == ']',
3445 "str: invalid regex: expected character class");
3446 int size = pattern.size() - 2;
3447 log_space_num_ways_ = math::detail::log_space(size);
3448 distinct_ = distinct_container<char>(pattern.substr(1, size));
3449 }
3450 // SEQ or OR.
3451 regex_node(const std::string &pattern, std::vector<regex_node> &children)
3452 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3453 if (pattern == "SEQ") {
3454 // Multiply the number of ways.
3455 log_space_num_ways_ = math::detail::LOG_ONE;
3456 for (const auto &child : children)
3457 log_space_num_ways_ += child.log_space_num_ways_;
3458 } else if (pattern == "OR") {
3459 // Add the number of ways.
3460 log_space_num_ways_ = math::detail::LOG_ZERO;
3461 for (const auto &child : children)
3462 log_space_num_ways_ = math::detail::add_log_space(
3463 log_space_num_ways_, child.log_space_num_ways_);
3464 } else
3465 tgen_ensure_against_bug("str: invalid regex: expected SEQ or OR");
3466
3467 children_ = std::move(children);
3468 children.clear();
3469 }
3470 // REP.
3471 regex_node(int left_bound, int right_bound, regex_node &child)
3472 : pattern_("REP"), left_bound_(left_bound), right_bound_(right_bound) {
3473 log_space_num_ways_ = math::detail::LOG_ZERO;
3474 for (int i = left_bound; i <= right_bound; ++i)
3475 log_space_num_ways_ = math::detail::add_log_space(
3476 log_space_num_ways_, i * child.log_space_num_ways_);
3477
3478 children_.push_back(std::move(child));
3479 }
3480};
3481
3482// State of the regex parser.
3483struct regex_state {
3484 std::vector<regex_node> cur; // Current sequence of nodes.
3485 std::vector<regex_node> branches; // Branches of the current OR group.
3486};
3487
3488// Creates a SEQ node from the current state.
3489inline regex_node make_regex_seq(regex_state &st) {
3490 return regex_node("SEQ", st.cur);
3491}
3492
3493// Finishes current state.
3494inline regex_node finish_regex_state(regex_state &st) {
3495 // SEQ.
3496 if (st.branches.empty())
3497 return make_regex_seq(st);
3498
3499 // OR.
3500 st.branches.push_back(make_regex_seq(st));
3501 return regex_node("OR", st.branches);
3502}
3503
3504// Parses a regex pattern into a tree, computing the number of ways to match the
3505// pattern.
3506inline regex_node parse_regex(std::string regex) {
3507 std::string new_regex;
3508 for (char c : regex)
3509 if (c != ' ')
3510 new_regex += c;
3511 swap(regex, new_regex);
3512 regex_state cur;
3513 std::vector<regex_state> stack;
3514
3515 for (size_t i = 0; i < regex.size(); ++i) {
3516 char c = regex[i];
3517
3518 if (c == '(') {
3519 // Pushes the current state to the stack.
3520 stack.push_back(std::move(cur));
3521 cur = regex_state();
3522 } else if (c == ')') {
3523 // Finishes the current state, and adds it to the parent.
3524 regex_node node = finish_regex_state(cur);
3525
3526 tgen_ensure(!stack.empty(), "str: invalid regex: unmatched `)`");
3527 cur = std::move(stack.back());
3528 stack.pop_back();
3529
3530 cur.cur.push_back(std::move(node));
3531 } else if (c == '|') {
3532 // Starts a new OR group.
3533 regex_node node = make_regex_seq(cur);
3534 cur.branches.push_back(std::move(node));
3535 } else if (c == '[') {
3536 // Parses a character class.
3537 std::string chars;
3538
3539 for (++i; i < regex.size() and regex[i] != ']'; ++i) {
3540 if (i + 2 < regex.size() and regex[i + 1] == '-') {
3541 char a = regex[i], b = regex[i + 2];
3542 if (a > b)
3543 std::swap(a, b);
3544 for (char x = a; x <= b; ++x)
3545 chars += x;
3546 i += 2;
3547 } else
3548 chars += regex[i];
3549 }
3550
3551 tgen_ensure(i < regex.size() and regex[i] == ']',
3552 "str: invalid regex: unmatched `[`");
3553 cur.cur.emplace_back("[" + chars + "]");
3554 } else if (c == '{') {
3555 // Parses a repetition.
3556 ++i;
3557 int l = -1, r = -1;
3558
3559 while (i < regex.size() and
3560 isdigit(static_cast<unsigned char>(regex[i]))) {
3561 if (l == -1)
3562 l = 0;
3563 tgen_ensure(l <= static_cast<int>(1e8),
3564 "str: invalid regex: number too large inside `{}`");
3565 l = 10 * l + (regex[i] - '0');
3566 ++i;
3567 }
3568
3569 if (i < regex.size() and regex[i] == ',') {
3570 ++i;
3571 while (i < regex.size() and
3572 isdigit(static_cast<unsigned char>(regex[i]))) {
3573 if (r == -1)
3574 r = 0;
3576 r <= static_cast<int>(1e8),
3577 "str: invalid regex: number too large inside `{}`");
3578 r = 10 * r + (regex[i] - '0');
3579 ++i;
3580 }
3581 } else
3582 r = l;
3583
3584 tgen_ensure(i < regex.size() and regex[i] == '}',
3585 "str: invalid regex: unmatched `{`");
3586 tgen_ensure(l != -1 and r != -1,
3587 "str: invalid regex: missing number inside `{}`");
3588 tgen_ensure(l <= r,
3589 "str: invalid regex: invalid range inside `{}`");
3590
3591 // Creates a REP node from the previous node.
3592 tgen_ensure(!cur.cur.empty(),
3593 "str: invalid regex: expected expression before `{}`");
3594
3595 regex_node rep(l, r, cur.cur.back());
3596 cur.cur.pop_back();
3597 cur.cur.push_back(std::move(rep));
3598 } else {
3599 // Creates a char node.
3600 cur.cur.emplace_back(std::string(1, c));
3601 }
3602 }
3603
3604 tgen_ensure(stack.empty(), "str: invalid regex: unmatched `(`");
3605 return finish_regex_state(cur);
3606}
3607
3608// Generates a uniformly random string that matches the given regex.
3609inline void gen_regex(const regex_node &node, std::string &str) {
3610 // For [chars], generate a random character from the list.
3611 if (node.pattern_[0] == '[') {
3612 str += node.pattern_[1 + next<int>(0, node.pattern_.size() - 3)];
3613 return;
3614 }
3615
3616 // For REP, generate a random number of times to repeat the pattern.
3617 if (node.left_bound_ != -1) {
3618 // Generates a random value W from 0 to num_ways.
3619 // log(W) = log(random(0, 1) * num_ways)
3620 // = log(random(0, 1)) + log(num_ways).
3621 double log_rand = math::detail::log_space(next<double>(0, 1)) +
3622 node.log_space_num_ways_;
3623 double cur_prob = math::detail::LOG_ZERO;
3624 double child_num_ways = node.children_[0].log_space_num_ways_;
3625
3626 for (int i = node.left_bound_; i <= node.right_bound_; ++i) {
3627 cur_prob =
3628 math::detail::add_log_space(cur_prob, i * child_num_ways);
3629 if (log_rand <= cur_prob) {
3630 for (int j = 0; j < i; ++j)
3631 gen_regex(node.children_[0], str);
3632 return;
3633 }
3634 }
3635
3636 tgen_ensure_against_bug(false,
3637 "str: log_rand > cur_prob in REP gen_regex");
3638 }
3639
3640 // For SEQ, generate all children.
3641 if (!node.children_.empty() and node.pattern_ == "SEQ") {
3642 for (const regex_node &child : node.children_)
3643 gen_regex(child, str);
3644 return;
3645 }
3646
3647 // For OR, generate a random child.
3648 if (!node.children_.empty() and node.pattern_ == "OR") {
3649 // Generates a random value W from 0 to num_ways.
3650 // log(W) = log(random(0, 1) * num_ways)
3651 // = log(random(0, 1)) + log(num_ways).
3652 double log_rand = math::detail::log_space(next<double>(0, 1)) +
3653 node.log_space_num_ways_;
3654 double cur_prob = math::detail::LOG_ZERO;
3655
3656 for (const regex_node &child : node.children_) {
3657 cur_prob = math::detail::add_log_space(cur_prob,
3658 child.log_space_num_ways_);
3659 if (log_rand <= cur_prob) {
3660 gen_regex(child, str);
3661 return;
3662 }
3663 }
3664
3665 tgen_ensure_against_bug(false,
3666 "str: log_rand > cur_prob in OR gen_regex");
3667 }
3668
3669 // For char, generate the character.
3670 detail::tgen_ensure_against_bug(
3671 node.pattern_.size() == 1,
3672 "str: invalid regex: expected single character, but got `" +
3673 node.pattern_ + "`");
3674 str += node.pattern_[0];
3675}
3676
3677// Formats a regex string with given arguments.
3678template <typename... Args>
3679std::string regex_format(const std::string &s, Args &&...args) {
3680 if constexpr (sizeof...(Args) == 0) {
3681 return s;
3682 } else {
3683 int size = std::snprintf(nullptr, 0, s.c_str(), args...) + 1;
3684 std::string buf(size, '\0');
3685 std::snprintf(buf.data(), size, s.c_str(), args...);
3686 buf.pop_back(); // remove '\0'
3687 return buf;
3688 }
3689}
3690
3691} // namespace detail
3692
3693/*
3694 * String generator.
3695 */
3696
3697struct str : gen_base<str> {
3698 std::optional<list<char>> list_; // List of characters.
3699 std::optional<detail::regex_node>
3700 root_; // Root node of the regex tree for the whole string.
3701
3702 // Creates generator for strings of size 'size', with random characters in
3703 // [value_left, value_right].
3704 str(int size, char value_left = 'a', char value_right = 'z') {
3705 tgen_ensure(size > 0, "str: size must be positive");
3706 list_ = list<char>(size, value_left, value_right);
3707 }
3708
3709 // Creates generator for strings of size 'size', with random characters in
3710 // 'chars'.
3711 str(int size, std::set<char> chars) {
3712 tgen_ensure(size > 0, "str: size must be positive");
3713 list_ = list<char>(size, chars);
3714 }
3715
3716 // Creates generator for strings that match the given regex.
3717 template <typename... Args> str(const std::string &regex, Args &&...args) {
3718 tgen_ensure(regex.size() > 0, "str: regex must be non-empty");
3719
3720 root_ = detail::parse_regex(
3721 detail::regex_format(regex, std::forward<Args>(args)...));
3722 }
3723
3724 // Restricts strings for str[idx] = value.
3725 str &fix(int idx, char character) {
3726 tgen_ensure(!root_, "str: cannot add restriction for regex");
3727 list_->fix(idx, character);
3728 return *this;
3729 }
3730
3731 // Restricts strings for list[S] to be equal, for given subset S of indices.
3732 str &equal(std::set<int> indices) {
3733 tgen_ensure(!root_, "str: cannot add restriction for regex");
3734 list_->equal(indices);
3735 return *this;
3736 }
3737
3738 // Restricts strings for str[idx_1] = str[idx_2].
3739 str &equal(int idx_1, int idx_2) {
3740 tgen_ensure(!root_, "str: cannot add restriction for regex");
3741 list_->equal(idx_1, idx_2);
3742 return *this;
3743 }
3744
3745 // Restricts strings for str[left..right] to have all equal values.
3746 str &equal_range(int left, int right) {
3747 tgen_ensure(!root_, "str: cannot add restriction for regex");
3748 list_->equal_range(left, right);
3749 return *this;
3750 }
3751
3752 // Restricts strings for all equal chars.
3754 tgen_ensure(!root_, "str: cannot add restriction for regex");
3755 list_->all_equal();
3756 return *this;
3757 }
3758
3759 // Restricts strings for str[left..right] to be a palindrome.
3760 str &palindrome(int left, int right) {
3761 tgen_ensure(!root_, "str: cannot add restriction for regex");
3762 tgen_ensure(0 <= left and left <= right and right < list_->size_,
3763 "str: range indices must be valid");
3764 for (int i = left; i < right - (i - left); ++i)
3765 equal(i, right - (i - left));
3766 return *this;
3767 }
3768
3769 // Restricts strings for the entire string to be a palindrome.
3771 tgen_ensure(!root_, "str: cannot add restriction for regex");
3772 return palindrome(0, list_->size_ - 1);
3773 }
3774
3775 // Restricts strings for str[S] to be different (distinct), for given subset
3776 // S of indices.
3777 str &different(std::set<int> indices) {
3778 tgen_ensure(!root_, "str: cannot add restriction for regex");
3779 list_->different(indices);
3780 return *this;
3781 }
3782
3783 // Restricts strings for str[idx_1] != str[idx_2].
3784 str &different(int idx_1, int idx_2) {
3785 tgen_ensure(!root_, "str: cannot add restriction for regex");
3786 list_->different(idx_1, idx_2);
3787 return *this;
3788 }
3789
3790 // Restricts lists for list[left..right] to have all different chars.
3791 str &different_range(int left, int right) {
3792 tgen_ensure(!root_, "str: cannot add restriction for regex");
3793 list_->different_range(left, right);
3794 return *this;
3795 }
3796
3797 // Restricts strings for all chars to be different.
3799 tgen_ensure(!root_, "str: cannot add restriction for regex");
3800 list_->all_different();
3801 return *this;
3802 }
3803
3804 // str value.
3806 using tgen_is_sequential_tag = detail::is_sequential_tag;
3807
3808 using value_type = char;
3809 using std_type = std::string;
3810 std::string str_;
3811
3812 value(const std::string &str) : str_(str) {
3813 tgen_ensure(!str_.empty(), "str: value: cannot be empty");
3814 }
3815
3816 // Fetches size.
3817 int size() const { return str_.size(); }
3818
3819 // Fetches position idx.
3820 char &operator[](int idx) {
3821 tgen_ensure(0 <= idx and idx < size(),
3822 "str: value: index out of bounds");
3823 return str_[idx];
3824 }
3825 const char &operator[](int idx) const {
3826 tgen_ensure(0 <= idx and idx < size(),
3827 "str: value: index out of bounds");
3828 return str_[idx];
3829 }
3830
3831 // Sorts characters in non-decreasing order.
3832 // O(n log n).
3834 std::sort(str_.begin(), str_.end());
3835 return *this;
3836 }
3837
3838 // Reverses string.
3839 // O(n).
3841 std::reverse(str_.begin(), str_.end());
3842 return *this;
3843 }
3844
3845 // Lowercases all characters.
3846 // O(n).
3848 for (char &c : str_)
3849 c = std::tolower(c);
3850 return *this;
3851 }
3852
3853 // Uppercases all characters.
3854 // O(n).
3856 for (char &c : str_)
3857 c = std::toupper(c);
3858 return *this;
3859 }
3860
3861 // Concatenates two values.
3862 // Linear.
3863 value operator+(const value &rhs) const {
3864 return value(str_ + rhs.str_);
3865 }
3866
3867 // Shuffles string uniformly.
3868 // O(n).
3870 for (int i = 0; i < size(); ++i)
3871 std::swap(str_[i], str_[next(0, size() - 1)]);
3872 return *this;
3873 }
3874
3875 // Returns a random character uniformly.
3876 // O(1).
3877 char pick() const { return str_[next<int>(0, size() - 1)]; }
3878
3879 // Returns str_[i] with probability proportional to distribution[i].
3880 // O(1).
3881 template <typename Dist>
3882 char pick_by_distribution(const std::vector<Dist> &distribution) const {
3883 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
3884 "value and distribution must have the same size");
3885 return str_[next_by_distribution(distribution)];
3886 }
3887 template <typename Dist>
3888 char pick_by_distribution(
3889 const std::initializer_list<Dist> &distribution) const {
3890 return pick_by_distribution(std::vector<Dist>(distribution));
3891 }
3892
3893 // Chooses k characters uniformly, as in a subsequence of size k.
3894 // O(n).
3895 value choose(int k) const {
3896 tgen_ensure(0 < k and k <= size(),
3897 "number of elements to choose must be valid");
3898 std::string new_str;
3899 int need = k;
3900 for (int i = 0; need > 0; ++i) {
3901 int left = size() - i;
3902 if (next(1, left) <= need) {
3903 new_str.push_back(str_[i]);
3904 need--;
3905 }
3906 }
3907 return value(new_str);
3908 }
3909
3910 // Prints to std::ostream.
3911 friend std::ostream &operator<<(std::ostream &out, const value &val) {
3912 return out << val.str_;
3913 }
3914
3915 // Gets a std::string representing the value.
3916 std::string to_std() const { return std_type(str_); }
3917 };
3918
3919 // Generates str value.
3920 // If created from restrictions: O(n log n).
3921 // If created from regex: expected linear.
3922 value gen() const {
3923 if (root_) {
3924 // Regex.
3925 std::string ret_str;
3926 gen_regex(*root_, ret_str);
3927 return value(ret_str);
3928 } else {
3929 // List.
3930 std::vector<char> vec = list_->gen().to_std();
3931 return value(std::string(vec.begin(), vec.end()));
3932 }
3933 }
3934};
3935
3936/************
3937 * *
3938 * PAIR *
3939 * *
3940 ************/
3941
3942namespace detail {
3943
3944// Generates pair first == second.
3945// O(1).
3946template <typename T> std::pair<T, T> gen_eq(T L1, T R1, T L2, T R2) {
3947 T L = std::max(L1, L2);
3948 T R = std::min(R1, R2);
3949
3950 tgen_ensure(L <= R, "pair: no valid values to generate");
3951 T x = next<T>(L, R);
3952 return {x, x};
3953}
3954
3955// Returns {R1-L1+1, R2-L2+1}.
3956template <typename T>
3957std::pair<u128, u128> get_n_and_m(T L1, T R1, T L2, T R2) {
3958 u128 n = static_cast<i128>(R1) - L1 + 1;
3959 u128 m = static_cast<i128>(R2) - L2 + 1;
3960 return {n, m};
3961}
3962
3963// Returns first + first+1 + ... + last,
3964// num_terms terms. Avoids overflow.
3965static u128 pos_arith_sum(u128 first, u128 last, u128 num_terms) {
3966 u128 x = first + last, y = num_terms;
3967
3968 // x * y / 2, avoiding overflow.
3969 if (x % 2 == 0)
3970 x /= 2;
3971 else
3972 y /= 2;
3973
3974 return x * y;
3975}
3976
3977// Generates pair first != second.
3978// O(1) expected.
3979template <typename T> std::pair<T, T> gen_neq(T L1, T R1, T L2, T R2) {
3980 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
3981
3982 T L_intersect = std::max(L1, L2);
3983 T R_intersect = std::min(R1, R2);
3984 u128 inter = static_cast<i128>(R_intersect) - L_intersect + 1;
3985
3986 u128 total = n * m - inter;
3987 tgen_ensure(total > 0, "pair: no valid values to generate");
3988
3989 // Runs O(1) expected times in the worst case.
3990 T a, b;
3991 do {
3992 a = next<T>(L1, R1);
3993 b = next<T>(L2, R2);
3994 } while (a == b);
3995
3996 return {a, b};
3997}
3998
3999// For lt, splits 'second' into two regions:
4000// 1) second <= R1 -> number of 'first' is (second - L1)
4001// 2) second > R1 -> number of 'first' is (R1 - L1 + 1)
4002// Returns {count_region1, count_region2}.
4003// O(1).
4004template <typename T>
4005std::pair<u128, u128> count_lt_regions(T L1, T R1, T L2, T R2) {
4006 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4007
4008 // 'second' must be >= L1 + 1.
4009 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);
4010 i128 R_second = R2;
4011
4012 // Split point for 'second'.
4013 i128 split = std::min<i128>(R_second, R1);
4014
4015 // Region 1: b in [L_second, split].
4016 u128 len1 = std::max<i128>(0, split - L_second + 1);
4017
4018 u128 count_region1 = 0;
4019 if (len1 > 0) {
4020 // For b in [L_second, split], there are (b - L1) ways.
4021 i128 first = L_second - L1;
4022 i128 last = split - L1;
4023
4024 // Arithmetic series first + (first + 1) + ... + last, len1 terms.
4025 count_region1 = pos_arith_sum(first, last, len1);
4026 }
4027
4028 // Region 2: b > R1.
4029 // For b in [R1+1, R_second], there are 'n' ways.
4030 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);
4031
4032 u128 len2 = std::max<i128>(0, R_second - L_second_region2 + 1);
4033 u128 count_region2 = len2 * n;
4034
4035 return {count_region1, count_region2};
4036}
4037
4038// Generates pair first < second.
4039// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4040template <typename T> std::pair<T, T> gen_lt(T L1, T R1, T L2, T R2) {
4041 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4042
4043 // 'second' needs to be at least L1 + 1 to have a valid value for
4044 // 'first'.
4045 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);
4046 i128 R_second = R2;
4047
4048 // Splits 'second' into two regions:
4049 // 1) b <= R1 -> number of 'first' is (b - L1);
4050 // 2) b > R1 -> number of 'first' is (R1 - L1 + 1).
4051 i128 split = std::min<i128>(R_second, R1);
4052
4053 auto [count_region1, count_region2] = count_lt_regions(L1, R1, L2, R2);
4054 u128 total = count_region1 + count_region2;
4055 tgen_ensure(total > 0, "pair: no valid values to generate");
4056
4057 u128 k = detail::next128(total);
4058 if (k < count_region1) {
4059 // Region 1: invert arithmetic series.
4060
4061 // For b in [L_second, split].
4062 u128 len1 = std::max<i128>(0, split - L_second + 1);
4063
4064 // We consider b in [L_second, L_second + d].
4065 // Each b contributes (b - L1) = base + (b - L_second).
4066 // So we sum: base + (base+1) + ... + (base+d)
4067 // d in [0, len1).
4068
4069 i128 base = L_second - L1;
4070 i128 lo = 0, hi = static_cast<i128>(len1) - 1;
4071
4072 while (lo < hi) {
4073 i128 mid = lo + (hi - lo) / 2;
4074
4075 if (pos_arith_sum(base, base + mid, mid + 1) <= k)
4076 lo = mid + 1;
4077 else
4078 hi = mid;
4079 }
4080 i128 d = lo;
4081
4082 // Subtracts prefix sum with d-1 terms from k.
4083 if (d > 0)
4084 k -= pos_arith_sum(base, base + d - 1, d);
4085
4086 return {L1 + static_cast<T>(k), L_second + d};
4087 } else {
4088 // Region 2: uniform block of size n.
4089 k -= count_region1;
4090
4091 // For b in [R1+1, R_second], there are 'n' ways.
4092 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);
4093
4094 return {L1 + static_cast<T>(k % n),
4095 L_second_region2 + static_cast<T>(k / n)};
4096 }
4097}
4098
4099// Generates pair first > second.
4100// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4101template <typename T> std::pair<T, T> gen_gt(T L1, T R1, T L2, T R2) {
4102 auto [first, second] = gen_lt(L2, R2, L1, R1);
4103 return {second, first};
4104}
4105
4106// Generates pair first <= second.
4107// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4108template <typename T> std::pair<T, T> gen_leq(T L1, T R1, T L2, T R2) {
4109 // Counts how many pairs are there with first = second.
4110 i128 L_intersect = std::max(L1, L2);
4111 i128 R_intersect = std::min(R1, R2);
4112 u128 eq_count = std::max<i128>(0, R_intersect - L_intersect + 1);
4113
4114 // Counts how many pairs are there with first < second.
4115 auto [lt_region1, lt_region2] = count_lt_regions(L1, R1, L2, R2);
4116 u128 lt_count = lt_region1 + lt_region2;
4117
4118 u128 total = eq_count + lt_count;
4119 tgen_ensure(total > 0, "pair: no valid values to generate");
4120
4121 if (detail::next128(total) < eq_count)
4122 return gen_eq(L1, R1, L2, R2);
4123 return gen_lt(L1, R1, L2, R2);
4124}
4125
4126// Generates pair first >= second.
4127// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4128template <typename T> std::pair<T, T> gen_geq(T L1, T R1, T L2, T R2) {
4129 auto [first, second] = gen_leq(L2, R2, L1, R1);
4130 return {second, first};
4131}
4132
4133}; // namespace detail
4134
4135/*
4136 * Pair generator.
4137 *
4138 * Pairs of integral types.
4139 */
4140
4141template <typename T> struct pair : gen_base<pair<T>> {
4142 std::pair<T, T> first_, second_; // Range of first and second values.
4143 // Type of restriction.
4144 enum class restriction_type { eq, neq, lt, gt, leq, geq, unspecified };
4145 restriction_type type_ = restriction_type::unspecified;
4146
4147 // Creates a pair with random values in [first_l, first_r] and [second_l,
4148 // second_r].
4149 pair(T first_left, T first_right, T second_left, T second_right)
4150 : first_(first_left, first_right), second_(second_left, second_right) {
4151 tgen_ensure(first_left <= first_right,
4152 "pair: first range must be valid");
4153 tgen_ensure(second_left <= second_right,
4154 "pair: second range must be valid");
4155 }
4156
4157 // Creates a pair with random values in [both_l, both_r].
4158 pair(T both_left, T both_right)
4159 : pair(both_left, both_right, both_left, both_right) {}
4160
4161 // Restricts pair for first = second.
4163 type_ = restriction_type::eq;
4164 return *this;
4165 }
4166
4167 // Restricts pair for first != second.
4169 type_ = restriction_type::neq;
4170 return *this;
4171 }
4172
4173 // Restricts pair for first < second.
4175 type_ = restriction_type::lt;
4176 return *this;
4177 }
4178
4179 // Restricts pair for first > second.
4181 type_ = restriction_type::gt;
4182 return *this;
4183 }
4184
4185 // Restricts pair for first <= second.
4187 type_ = restriction_type::leq;
4188 return *this;
4189 }
4190
4191 // Restricts pair for first >= second.
4193 type_ = restriction_type::geq;
4194 return *this;
4195 }
4196
4197 // Pair value.
4199 using value_type = T;
4200 using std_type = std::pair<T, T>;
4201
4202 std::pair<T, T> pair_;
4203 char sep_;
4204
4205 value(const std::pair<T, T> &pair) : pair_(pair), sep_(' ') {}
4206 value(const T &first, const T &second)
4207 : pair_(first, second), sep_(' ') {}
4208
4209 T first() const { return pair_.first; }
4210 T second() const { return pair_.second; }
4211
4212 // Sets the separator for the pair, for printing.
4213 value &separator(char sep) {
4214 sep_ = sep;
4215 return *this;
4216 }
4217
4218 // Prints to std::ostream, separated by sep_.
4219 friend std::ostream &operator<<(std::ostream &out, const value &val) {
4220 return out << val.pair_.first << val.sep_ << val.pair_.second;
4221 }
4222
4223 // Gets a std::pair representing the value.
4224 auto to_std() const {
4225 if constexpr (!detail::is_generator_value<T>::value) {
4226 return pair_;
4227 } else {
4228 std::pair<typename T::std_type, typename T::std_type> pair(
4229 pair_.first.to_std(), pair_.second.to_std());
4230 return pair;
4231 }
4232 }
4233 };
4234
4235 // Generates a random pair.
4236 // O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4237 value gen() const {
4238 T L1 = first_.first, R1 = first_.second;
4239 T L2 = second_.first, R2 = second_.second;
4240
4241 switch (type_) {
4242 case restriction_type::unspecified:
4243 return {next<T>(L1, R1), next<T>(L2, R2)};
4244 case restriction_type::eq:
4245 return detail::gen_eq<T>(L1, R1, L2, R2);
4246 case restriction_type::neq:
4247 return detail::gen_neq<T>(L1, R1, L2, R2);
4248 case restriction_type::lt:
4249 return detail::gen_lt<T>(L1, R1, L2, R2);
4250 case restriction_type::gt:
4251 return detail::gen_gt<T>(L1, R1, L2, R2);
4252 case restriction_type::leq:
4253 return detail::gen_leq<T>(L1, R1, L2, R2);
4254 case restriction_type::geq:
4255 return detail::gen_geq<T>(L1, R1, L2, R2);
4256 }
4257 throw detail::error("pair: unknown restriction type");
4258 }
4259};
4260
4261/************
4262 * *
4263 * TREE *
4264 * *
4265 ************/
4266
4267namespace detail {
4268
4269// Generates edges from Prufer sequence.
4270// O(n).
4271inline std::vector<std::pair<int, int>> edges_from_prufer(std::vector<int> p) {
4272 int n = p.size() + 2;
4273
4274 // Degrees.
4275 std::vector<int> d(n, 1);
4276 for (int i : p)
4277 d[i]++;
4278
4279 // Adds last vertex.
4280 p.push_back(n - 1);
4281
4282 // Finds first vertex with degree 1.
4283 int idx, u;
4284 idx = u = find(d.begin(), d.end(), 1) - d.begin();
4285
4286 // Generates edges.
4287 std::vector<std::pair<int, int>> edges;
4288 for (int v : p) {
4289 edges.emplace_back(u, v);
4290 if (--d[v] == 1 and v < idx)
4291 u = v;
4292 else
4293 idx = u = find(d.begin() + idx + 1, d.end(), 1) - d.begin();
4294 }
4295 return edges;
4296}
4297
4298// Disjoint set union (union-find) for connectivity queries.
4299struct dsu {
4300 std::vector<int> parent_;
4301 std::vector<unsigned char> rank_;
4302
4303 // Creates a dsu with `n` elements, indexed from 0 to n-1.
4304 // Initially every element is in its own set.
4305 // O(n).
4306 dsu(int n) : parent_(n), rank_(n, 0) {
4307 for (int i = 0; i < n; ++i)
4308 parent_[i] = i;
4309 }
4310
4311 // Adds new elements to the dsu, each in their own new set.
4312 // O(k) amortized.
4313 void add_elements(int k) {
4314 for (int i = 0; i < k; ++i) {
4315 int new_id = parent_.size();
4316 parent_.push_back(new_id);
4317 rank_.push_back(0);
4318 }
4319 }
4320
4321 // Finds representative of set containing i.
4322 // O(alpha(n)) amortized, O(log n) worst case.
4323 int find(int i) {
4324 return parent_[i] == i ? i : parent_[i] = find(parent_[i]);
4325 }
4326
4327 // Merges components of `a` and `b`. Returns if the sets were united, and
4328 // false if a and b were in the same set.
4329 // O(alpha(n)) amortized, O(log n) worst case.
4330 bool unite(int a, int b) {
4331 a = find(a);
4332 b = find(b);
4333 if (a == b)
4334 return false;
4335 if (rank_[a] > rank_[b])
4336 std::swap(a, b);
4337 parent_[a] = b;
4338 if (rank_[a] == rank_[b])
4339 ++rank_[b];
4340 return true;
4341 }
4342};
4343
4344} // namespace detail
4345
4346// Forward declaration of wgraph.
4347template <typename VWeight, typename EWeight> struct wgraph;
4348
4349/*
4350 * Tree generator.
4351 *
4352 * Unrooted trees with `n` vertices, indexed from 0 to n-1.
4353 * These are unrooted undirected labeled trees, that is, isomorphism is not
4354 * taken into account. VWeight is the type of vertex weights, and EWeight is
4355 * the type of edge weights. Generator does not generate weights. The weights
4356 * are to be set in the wtree::value.
4357 */
4358
4359template <typename VWeight, typename EWeight>
4360struct wtree : gen_base<wtree<VWeight, EWeight>> {
4361 int n_; // Number of vertices.
4362 std::set<std::pair<int, int>> edges_; // Edges that were set.
4363
4364 // Creates tree generator with `n` vertices.
4365 // O(1).
4366 wtree(int n) : n_(n) {
4367 tgen_ensure(n > 0, "wtree: number of vertices must be positive");
4368 }
4369
4370 // Adds edge between u and v (this edge must be generated).
4371 // O(log n).
4372 wtree &add_edge(int u, int v) {
4373 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,
4374 "wtree: vertices must be indexed in [0, n)");
4375 tgen_ensure(u != v, "wtree: cannot add self loop to tree");
4376
4377 if (u > v)
4378 std::swap(u, v);
4379 edges_.emplace(u, v);
4380 return *this;
4381 }
4382
4383 // Tree value.
4384 //
4385 // Edges are stored in both directions in adjacency list, but only u < v in
4386 // edge list.
4388 using std_type = std::pair<int, std::vector<std::set<int>>>;
4389
4390 int n_; // Number of vertices.
4391 std::vector<std::set<int>> adj_; // Adjacency list.
4392 std::vector<std::pair<int, int>> edges_; // Edge list.
4393 bool add_1_; // If should add 1 for printing vertex ids.
4394 bool print_n_; // If should print n.
4395 std::optional<int> print_parents_; // If should print in parent style
4396 // (stores the root).
4397 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.
4398 std::optional<std::vector<EWeight>>
4399 edge_weights_; // Edge weights (in same order as edges_).
4400 detail::dsu dsu_; // Connectivity of current edges (for cycle checks).
4401
4402 // Creates value from adjacency list.
4403 // O(n).
4404 value(const std::vector<std::set<int>> &adj)
4405 : n_(static_cast<int>(adj.size())), adj_(adj), add_1_(false),
4406 print_n_(false), dsu_(n_) {
4407 for (int u = 0; u < n_; ++u)
4408 for (auto v : adj[u]) {
4410 0 <= v and v < n_,
4411 "wtree: value: vertices must be indexed in [0, n)");
4412 // Symmetric adjacency: count each undirected edge once.
4413 if (u < v) {
4414 edges_.emplace_back(u, v);
4416 dsu_.unite(u, v),
4417 "wtree: value: initial graph must form a tree");
4418 }
4419 }
4420 }
4421
4422 // Creates value from `n` and edge list.
4423 // O(n).
4424 value(int n, const std::vector<std::pair<int, int>> &edges)
4425 : n_(n), adj_(n), add_1_(false), print_n_(false), dsu_(n) {
4426 edges_.reserve(edges.size());
4427 for (auto [u, v] : edges) {
4428 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n,
4429 "wtree: value: vertices must be indexed in [0, n)");
4430 tgen_ensure(dsu_.unite(u, v),
4431 "wtree: value: initial graph must form a tree");
4432 if (u > v)
4433 std::swap(u, v);
4434 edges_.emplace_back(u, v);
4435 adj_[u].insert(v);
4436 adj_[v].insert(u);
4437 }
4438 }
4439 value(int n, const std::set<std::pair<int, int>> &edges)
4440 : value(n, std::vector<std::pair<int, int>>(edges.begin(),
4441 edges.end())) {}
4442 value(int n, const std::initializer_list<std::pair<int, int>> &edges)
4443 : value(n, std::vector<std::pair<int, int>>(edges)) {}
4444
4445 // Creates tree from graph via Kruskal-like random spanning tree.
4446 // Implemented after wgraph definition.
4447 // O(n + m alpha(n)).
4448 value(const typename wgraph<VWeight, EWeight>::value &g);
4449
4450 // Weight type conversion.
4451 // O(n).
4452 template <typename NewVWeight, typename NewEWeight>
4453 typename wtree<NewVWeight, NewEWeight>::value
4454 convert_weight_types() const {
4455 tgen_ensure(!vertex_weights_.has_value() and
4456 !edge_weights_.has_value(),
4457 "wtree: value: cannot convert weight type after "
4458 "assigning weights");
4459
4460 typename wtree<NewVWeight, NewEWeight>::value new_tree(adj_);
4461 new_tree.add_1_ = add_1_;
4462 new_tree.print_n_ = print_n_;
4463 new_tree.print_parents_ = print_parents_;
4464 return new_tree;
4465 }
4466
4467 // Fetches number of vertices.
4468 int n() const { return n_; }
4469
4470 // Fetches a const ref. to adjacency list.
4471 const std::vector<std::set<int>> &adj() const { return adj_; }
4472
4473 // Fetches a const ref. to edge list.
4474 const std::vector<std::pair<int, int>> &edges() const { return edges_; }
4475
4476 // Fetches a const ref. to vertex weights.
4478 return vertex_weights_;
4479 }
4480
4481 // Fetches a const ref. to edge weights.
4483 return edge_weights_;
4484 }
4485
4486 // Sets vertex weights.
4487 // O(n).
4488 template <typename NewVWeight = VWeight>
4489 typename wtree<NewVWeight, EWeight>::value set_vertex_weights(
4490 const std::vector<NewVWeight> &vertex_weights) const {
4491 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),
4492 "wtree: value: must give `n` vertex weights");
4493
4494 auto new_tree = convert_weight_types<NewVWeight, EWeight>();
4495 new_tree.vertex_weights_ = vertex_weights;
4496 return new_tree;
4497 }
4498
4499 // Sets edge weights.
4500 // O(n).
4501 template <typename NewEWeight = EWeight>
4502 typename wtree<VWeight, NewEWeight>::value
4503 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {
4505 edge_weights.size() == edges().size(),
4506 "wtree: value: must give `edges().size()` edge weights");
4507
4508 auto new_tree = convert_weight_types<VWeight, NewEWeight>();
4509 new_tree.edge_weights_ = edge_weights;
4510 return new_tree;
4511 }
4512
4513 // Enables edge-weighted mode before adding weighted edges
4514 // incrementally. The tree must have no edges yet. O(1).
4516 tgen_ensure(edges().size() == 0,
4517 "wtree: value: edge_weighted requires a tree with no "
4518 "edges");
4519 tgen_ensure(!edge_weights_.has_value(),
4520 "wtree: value: tree is already edge-weighted");
4521
4522 edge_weights_ = std::vector<EWeight>();
4523 return *this;
4524 }
4525
4526 // Adds 1 to vertex ids, for printing.
4527 // O(1).
4529 add_1_ = true;
4530 return *this;
4531 }
4532
4533 // Prints `n` on a new line before printing the tree.
4534 // O(1).
4536 print_n_ = true;
4537 return *this;
4538 }
4539
4540 // Prints the tree in parent style.
4541 // If root = -1, the root is considered to be 0, and its parent is not
4542 // printed. Otherwise, prints the parent of the root as -1. If root = n,
4543 // randomizes the root. O(1).
4544 value &print_parents(int root = -1) {
4545 tgen_ensure(root == -1 or (0 <= root and root < n()) or root == n(),
4546 "wtree: value: root must be -1, `n`, or in [0, n)");
4547 print_parents_ = root;
4548 return *this;
4549 }
4550
4551 // Shuffles the tree's vertex labels (except those in `indices`,
4552 // which keep their current label) and edge order. The change is
4553 // applied eagerly to the underlying adjacency list, edge list,
4554 // vertex weights and edge weights.
4555 // O(n).
4556 value &shuffle_except(std::set<int> indices) {
4557 // Builds the relabeling: for each vertex `i`, `new_label[i]` is
4558 // its new id. Vertices in `indices` keep their label; the others
4559 // are permuted among themselves.
4560 std::vector<int> new_label(n());
4561 std::vector<int> shuffled;
4562 for (int i = 0; i < n(); ++i) {
4563 if (indices.count(i))
4564 new_label[i] = i;
4565 else
4566 shuffled.push_back(i);
4567 }
4568 std::vector<int> targets = shuffled;
4569 tgen::shuffle(targets.begin(), targets.end());
4570 for (size_t k = 0; k < shuffled.size(); ++k)
4571 new_label[shuffled[k]] = targets[k];
4572
4573 // Rewrites adjacency list with new labels.
4574 std::vector<std::set<int>> new_adj(n());
4575 for (int u = 0; u < n(); ++u)
4576 for (int v : adj_[u])
4577 new_adj[new_label[u]].insert(new_label[v]);
4578 adj_ = std::move(new_adj);
4579
4580 // Rewrites edges with new labels (canonical undirected order).
4581 for (auto &[u, v] : edges_) {
4582 u = new_label[u];
4583 v = new_label[v];
4584 if (u > v)
4585 std::swap(u, v);
4586 }
4587
4588 // Permutes vertex weights to match the new labels.
4589 if (vertex_weights_.has_value()) {
4590 std::vector<VWeight> new_vw(n());
4591 for (int i = 0; i < n(); ++i)
4592 new_vw[new_label[i]] = (*vertex_weights_)[i];
4593 vertex_weights_ = std::move(new_vw);
4594 }
4595
4596 // Rebuilds the dsu so future `add_edge` calls see the new labels.
4597 dsu_ = detail::dsu(n());
4598 for (auto [u, v] : edges_)
4599 dsu_.unite(u, v);
4600
4601 // Shuffles edge order, keeping edge weights aligned.
4602
4603 std::vector<int> perm(edges_.size());
4604 std::iota(perm.begin(), perm.end(), 0);
4605 tgen::shuffle(perm.begin(), perm.end());
4606
4607 std::vector<std::pair<int, int>> new_edges;
4608 std::optional<std::vector<EWeight>> new_ew;
4609 if (edge_weights_.has_value())
4610 new_ew = std::vector<EWeight>();
4611 for (int i : perm) {
4612 new_edges.push_back(edges_[i]);
4613 if (new_ew.has_value())
4614 new_ew->push_back((*edge_weights_)[i]);
4615 }
4616 edges_ = new_edges;
4617 if (new_ew.has_value())
4618 edge_weights_ = new_ew;
4619
4620 return *this;
4621 }
4622
4623 // Shuffles the tree's vertices and edge order.
4624 // O(n).
4625 value &shuffle() { return shuffle_except({}); }
4626
4627 // Adds edge (u, v).
4628 // O(log n) amortized.
4629 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {
4630 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),
4631 "wtree: value: vertex ids must be valid");
4632
4633 if (u > v)
4634 std::swap(u, v);
4635
4636 if (adj_[u].count(v))
4637 return *this;
4638
4639 adj_[u].insert(v);
4640 adj_[v].insert(u);
4641 edges_.emplace_back(u, v);
4642 tgen_ensure(dsu_.unite(u, v),
4643 "wtree: value: added edge must not create a cycle");
4644
4645 if (w.has_value()) {
4646 tgen_ensure(edge_weights().has_value(),
4647 "wtree: value: cannot add weighted edge to "
4648 "edge-unweighted tree");
4649
4650 edge_weights_->push_back(*w);
4651 } else
4652 tgen_ensure(!edge_weights().has_value(),
4653 "wtree: value: cannot add unweighted edge to "
4654 "edge-weighted tree");
4655
4656 return *this;
4657 }
4658
4659 // Links tree with another `rhs`, adding the edge between u (in left
4660 // tree) and v (in right tree). Ids for added vertices are updated
4661 // accordingly.
4662 // O(rhs.n + rhs.m * log n) amortized.
4663 value &link(const value &rhs, int new_u, int new_v,
4664 std::optional<EWeight> new_w = std::nullopt) {
4665 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and
4666 new_v < rhs.n(),
4667 "wtree: value: vertex ids must be valid");
4668
4669 // Edges from right-hand side.
4670 int shift = n();
4671 add_vertices(rhs.n(), rhs.vertex_weights());
4672 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {
4673 auto [u, v] = rhs.edges()[i];
4674 add_edge(shift + u, shift + v,
4675 rhs.edge_weights().has_value()
4676 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4677 : std::nullopt);
4678 }
4679
4680 // New edge.
4681 add_edge(new_u, shift + new_v, new_w);
4682
4683 return *this;
4684 }
4685
4686 // Glues the tree with another `rhs` such that index_pairs[i].first is
4687 // considered to be the same as index_pairs[i].second. Ids for added
4688 // vertices are updated accordingly.
4689 // O(rhs.n + rhs.m * log n) amortized.
4690 value &glue(const value &rhs,
4691 std::set<std::pair<int, int>> index_pairs) {
4692 // Checks validity of indices.
4693 std::set<int> idx_left, idx_right;
4694 std::vector<int> right_id_to_left(rhs.n(), -1);
4695 for (auto [l, r] : index_pairs) {
4697 0 <= l and l < n() and 0 <= r and r < rhs.n(),
4698 "wtree: value: vertex indices to glue must be valid");
4699 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,
4700 "wtree: value: must not have repeated indices "
4701 "on the same side to glue");
4702
4703 idx_left.insert(l);
4704 idx_right.insert(r);
4705 right_id_to_left[r] = l;
4706 }
4707
4708 // Computes new ids of right vertices.
4709 std::vector<int> new_right_id(rhs.n(), -1);
4710 int intersection_lt = 0;
4711 std::optional<std::vector<VWeight>> rhs_vertex_weights;
4712 for (int i = 0; i < rhs.n(); ++i) {
4713 if (right_id_to_left[i] != -1) {
4714 // Is in intersection.
4715 ++intersection_lt;
4716 new_right_id[i] = right_id_to_left[i];
4717 } else {
4718 // New id.
4719 new_right_id[i] = n() + i - intersection_lt;
4720 if (rhs.vertex_weights().has_value()) {
4721 if (!rhs_vertex_weights.has_value())
4722 rhs_vertex_weights = std::vector<VWeight>();
4723 rhs_vertex_weights->push_back(
4724 (*rhs.vertex_weights())[i]);
4725 }
4726 }
4727 }
4728
4729 // Adds new vertices and edges.
4730 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
4731 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {
4732 auto [u, v] = rhs.edges()[i];
4733 add_edge(new_right_id[u], new_right_id[v],
4734 rhs.edge_weights().has_value()
4735 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4736 : std::nullopt);
4737 }
4738
4739 return *this;
4740 }
4741 value &glue(const value &rhs,
4742 std::initializer_list<std::pair<int, int>> il) {
4743 return glue(rhs, std::set<std::pair<int, int>>(il));
4744 }
4745
4746 // Glues the tree with another `rhs` at `indices`. That is, idx in
4747 // `indices` are considered to be the same vertex. Ids for added
4748 // vertices are updated accordingly.
4749 // O(rhs.n).
4750 value &glue(const value &rhs, std::set<int> indices) {
4751 std::set<std::pair<int, int>> index_pairs;
4752 for (auto i : indices)
4753 index_pairs.emplace(i, i);
4754 return glue(rhs, index_pairs);
4755 }
4756 value &glue(const value &rhs, const std::initializer_list<int> &il) {
4757 return glue(rhs, std::set<int>(il));
4758 }
4759
4760 // Prints to std::ostream.
4761 // O(n).
4762 friend std::ostream &operator<<(std::ostream &out, const value &val) {
4763 if (val.print_n_)
4764 out << val.n() << '\n';
4765
4766 // Prints vertex weights.
4767 if (val.vertex_weights()) {
4768 for (int i = 0; i < val.n(); ++i) {
4769 if (i > 0)
4770 out << " ";
4771 out << (*val.vertex_weights())[i];
4772 }
4773 out << '\n';
4774 }
4775
4776 tgen_ensure(static_cast<int>(val.edges().size()) == val.n() - 1,
4777 "wtree: value: invalid tree to print (number of edges "
4778 "must be `n` - 1)");
4779
4780 // Prints in parent style.
4781 if (val.print_parents_.has_value()) {
4782 tgen_ensure(!val.edge_weights().has_value(),
4783 "wtree: value: cannot print parent style if edges "
4784 "are weighted");
4785
4786 int root = *val.print_parents_;
4787 bool skip_parent_0 = root == -1;
4788 if (root == -1)
4789 root = 0;
4790 if (root == val.n())
4791 root = next(0, val.n() - 1);
4792
4793 std::vector<int> parent(val.n(), -1);
4794
4795 std::queue<int> q;
4796 std::vector<int> vis(val.n(), false);
4797 q.push(root);
4798 vis[root] = true;
4799
4800 while (q.size()) {
4801 int u = q.front();
4802 q.pop();
4803 for (int v : val.adj()[u])
4804 if (!vis[v]) {
4805 vis[v] = true;
4806 q.push(v);
4807 parent[v] = u;
4808 }
4809 }
4810
4811 if (skip_parent_0) {
4812 for (int i = 1; i < val.n(); ++i) {
4814 parent[i] < i,
4815 "wtree: value: parent of i must be less than i for "
4816 "printing in parent style if root is -1");
4817
4818 if (i > 1)
4819 out << " ";
4820 out << parent[i] + val.add_1_;
4821 }
4822 } else {
4823 for (int i = 0; i < val.n(); ++i) {
4824 if (i > 0)
4825 out << " ";
4826 out << (parent[i] == -1 ? -1 : parent[i]) + val.add_1_;
4827 }
4828 }
4829
4830 out << '\n';
4831 return out;
4832 }
4833
4834 // Prints edges.
4835 for (int i = 0; i < static_cast<int>(val.edges().size()); ++i) {
4836 auto [u, v] = val.edges()[i];
4837 out << (u + val.add_1_) << " " << (v + val.add_1_);
4838
4839 // Edge weight.
4840 if (val.edge_weights().has_value())
4841 out << " " << (*val.edge_weights())[i];
4842
4843 out << '\n';
4844 }
4845
4846 return out;
4847 }
4848
4849 // Gets a std::pair<n, adj> representing the value.
4850 std::pair<int, std::vector<std::set<int>>> to_std() const {
4851 return std_type(n_, adj_);
4852 }
4853
4854 private:
4855 // Adds `k` vertices to the tree (labeled n, n+1, ...n+k-1). Updates
4856 // `n` accordingly. This makes the tree invalid (not a tree anymore).
4857 // O(k) amortized.
4858 value &add_vertices(int k, std::optional<std::vector<VWeight>>
4859 new_vertex_weights = std::nullopt) {
4860 n_ += k;
4861 adj_.resize(n());
4862 if (new_vertex_weights.has_value()) {
4863 tgen_ensure(vertex_weights().has_value(),
4864 "wtree: value: cannot add weighted vertices to "
4865 "vertex-unweighted tree");
4867 static_cast<int>(new_vertex_weights->size()) == k,
4868 "wtree: value: number of vertex weights must be equal "
4869 "to number of added vertices");
4870
4871 vertex_weights_->insert(vertex_weights_->end(),
4872 new_vertex_weights->begin(),
4873 new_vertex_weights->end());
4874 } else
4875 tgen_ensure(!vertex_weights().has_value(),
4876 "wtree: value: cannot add unweighted vertices to "
4877 "vertex-weighted tree");
4878
4879 dsu_.add_elements(k);
4880
4881 return *this;
4882 }
4883 };
4884
4885 // Generates tree value.
4886 // O(n).
4887 value gen() const {
4888 // Constructs adjacency list.
4889 std::vector<std::vector<int>> adj(n_);
4890 for (auto [u, v] : edges_) {
4891 adj[u].push_back(v);
4892 adj[v].push_back(u);
4893 }
4894
4895 std::vector<int> comp_size;
4896 std::vector<std::vector<int>> component_ids;
4897 std::vector<bool> vis(n_, false);
4898 std::queue<int> q;
4899
4900 for (int i = 0; i < n_; ++i) {
4901 if (vis[i])
4902 continue;
4903
4904 vis[i] = true;
4905 q.push(i);
4906 comp_size.push_back(0);
4907 component_ids.emplace_back();
4908 while (q.size()) {
4909 int u = q.front();
4910 q.pop();
4911 ++comp_size.back();
4912 component_ids.back().push_back(u);
4913 for (int v : adj[u]) {
4914 if (!vis[v]) {
4915 vis[v] = true;
4916 q.push(v);
4917 }
4918 }
4919 }
4920 }
4921
4922 // Creates edges connecting the connected components by treating them as
4923 // vertices.
4924 std::vector<std::pair<int, int>> new_edges(edges_.begin(),
4925 edges_.end());
4926 if (comp_size.size() > 1) {
4927 std::vector<int> prufer_values =
4928 many_by_distribution(comp_size.size() - 2, comp_size);
4929 for (auto [u, v] : detail::edges_from_prufer(prufer_values))
4930 new_edges.emplace_back(pick(component_ids[u]),
4931 pick(component_ids[v]));
4932 }
4933
4934 return value(n_, new_edges);
4935 }
4936
4937 // Generates a (not uniformly) random skewed tree.
4938 // Vertex 0 is the root. For each i in 1 .. n-1, parent(i) is
4939 // wnext(i, elongation), i.e. a value in [0, i) with skew controlled by
4940 // elongation (see wnext).
4941 // If elongation is small enough, generates a star (center 0).
4942 // If elongation is large enough, generates a path (endpoints 0 and n-1).
4943 // O(n).
4944 static value gen_skewed(int n, int elongation) {
4945 std::vector<std::pair<int, int>> edges;
4946 for (int i = 1; i < n; ++i)
4947 edges.emplace_back(i, wnext<int>(i, elongation));
4948 return value(n, edges);
4949 }
4950
4951 // Kruskal-like random tree: random vertex pairs until connected.
4952 // Not uniformly random.
4953 // O(n log(n) alpha(n)) expected.
4954 static value gen_kruskal(int n) {
4955 tgen_ensure(n > 0, "wtree: gen_kruskal: n must be positive");
4956 if (n == 1)
4957 return value(1, {});
4958
4959 detail::dsu components(n);
4960 std::vector<std::pair<int, int>> edges;
4961 edges.reserve(n - 1);
4962 while (edges.size() < size_t(n - 1)) {
4963 int u = next(0, n - 1);
4964 int v = next(0, n - 1);
4965 if (u == v)
4966 continue;
4967 if (components.unite(u, v))
4968 edges.emplace_back(u, v);
4969 }
4970 return value(n, edges);
4971 }
4972};
4973
4974/*
4975 * Other types of weighted-ness.
4976 */
4977
4978// Vertex weighted tree.
4979template <typename VWeight> using vtree = wtree<VWeight, int>;
4980
4981// Edge weighted tree.
4982template <typename EWeight> using etree = wtree<int, EWeight>;
4983
4984// Unweighted tree.
4985using tree = wtree<int, int>;
4986
4987/*************
4988 * *
4989 * GRAPH *
4990 * *
4991 *************/
4992
4993namespace detail {
4994
4995// Canonical undirected edge key for duplicate detection; stores (min(u, v),
4996// max(u, v)). O(1).
4997inline uint64_t undirected_edge_key(int u, int v) {
4998 if (u > v)
4999 std::swap(u, v);
5000 return (static_cast<uint64_t>(u) << 32) |
5001 static_cast<uint64_t>(static_cast<uint32_t>(v));
5002}
5003
5004// Directed edge key for duplicate detection; stores (u, v).
5005// O(1).
5006inline uint64_t directed_edge_key(int u, int v) {
5007 return (static_cast<uint64_t>(u) << 32) |
5008 static_cast<uint64_t>(static_cast<uint32_t>(v));
5009}
5010
5011// Maximum number of edges in a simple graph on n vertices.
5012// O(1).
5013inline long long max_graph_edges(int n, bool directed, bool self_loops) {
5014 if (n <= 0)
5015 return 0;
5016 if (directed)
5017 return self_loops ? static_cast<long long>(n) * n
5018 : static_cast<long long>(n) * (n - 1);
5019 return self_loops ? static_cast<long long>(n) * (n + 1) / 2
5020 : static_cast<long long>(n) * (n - 1) / 2;
5021}
5022
5023// Uniform random edge for rejection sampling.
5024// O(1) expected.
5025inline std::pair<int, int> get_random_graph_edge(int n, bool directed,
5026 bool self_loops) {
5027 if (directed) {
5028 if (self_loops)
5029 return {next<int>(0, n - 1), next<int>(0, n - 1)};
5030 int u = next<int>(0, n - 1);
5031 int v = next<int>(0, n - 1);
5032 while (u == v)
5033 v = next<int>(0, n - 1);
5034 return {u, v};
5035 }
5036 if (self_loops) {
5037 int u = next<int>(0, n - 1);
5038 int v = next<int>(0, n - 1);
5039 if (u > v)
5040 std::swap(u, v);
5041 return {u, v};
5042 }
5043 int u = next<int>(0, n - 1);
5044 int v = next<int>(0, n - 1);
5045 while (u == v)
5046 v = next<int>(0, n - 1);
5047 if (u > v)
5048 std::swap(u, v);
5049 return {u, v};
5050}
5051
5052// Decodes a linear edge index to (u, v) for an undirected simple graph,
5053// with u < v.
5054// O(log n).
5055inline std::pair<int, int> decode_undirected_simple_edge(int n, long long idx) {
5056 auto base = [&](int u) -> long long {
5057 return static_cast<long long>(u) * (n - 1) -
5058 static_cast<long long>(u) * (u - 1) / 2;
5059 };
5060 int lo = 0, hi = n - 2;
5061 while (lo < hi) {
5062 int mid = (lo + hi + 1) / 2;
5063 if (base(mid) <= idx)
5064 lo = mid;
5065 else
5066 hi = mid - 1;
5067 }
5068 return {lo, lo + 1 + int(idx - base(lo))};
5069}
5070
5071// Decodes a linear edge index to (u, v) for an undirected graph with loops,
5072// with u <= v.
5073// O(log n).
5074inline std::pair<int, int> decode_undirected_loops_edge(int n, long long idx) {
5075 auto base = [&](int u) -> long long {
5076 return static_cast<long long>(u) * n -
5077 static_cast<long long>(u) * (u - 1) / 2;
5078 };
5079 int lo = 0, hi = n - 1;
5080 while (lo < hi) {
5081 int mid = (lo + hi + 1) / 2;
5082 if (base(mid) <= idx)
5083 lo = mid;
5084 else
5085 hi = mid - 1;
5086 }
5087 return {lo, lo + int(idx - base(lo))};
5088}
5089
5090// Decodes a linear edge index to (u, v) for a directed simple graph (no loops).
5091// O(1).
5092inline std::pair<int, int> decode_directed_simple_edge(int n, long long idx) {
5093 int u = idx / (n - 1);
5094 int rem = idx % (n - 1);
5095 return {u, rem + (rem >= u)};
5096}
5097
5098// Decodes a linear edge index according to graph mode.
5099// O(log n) for undirected, O(1) for directed.
5100inline std::pair<int, int>
5101decode_graph_edge_index(int n, long long idx, bool directed, bool self_loops) {
5102 if (directed) {
5103 if (self_loops)
5104 return {int(idx / n), int(idx % n)};
5105 return decode_directed_simple_edge(n, idx);
5106 }
5107 if (self_loops)
5108 return decode_undirected_loops_edge(n, idx);
5109 return decode_undirected_simple_edge(n, idx);
5110}
5111
5112} // namespace detail
5113
5114/*
5115 * Graph generator.
5116 *
5117 * Graphs of `n` vertices labeled from 0 to n-1 and `m` edges.
5118 * These are labeled graphs, that is, isomorphism is not taken into
5119 * account. VWeight is the type of vertex weights, and EWeight is the type of
5120 * edge weights. Generator does not generate weights. The weights are to be set
5121 * in the wgraph::value.
5122 */
5123
5124template <typename VWeight, typename EWeight>
5125struct wgraph : gen_base<wgraph<VWeight, EWeight>> {
5126 int n_, m_; // Number of vertices and edges.
5127 std::set<std::pair<int, int>> edges_; // Edges that were set.
5128 bool is_directed_; // If graph is directed.
5129 bool has_self_loops_; // If self-loops are allowed.
5130
5131 // Creates graph generator with `n` vertices and `m` edges.
5132 // Additionally, you can set if the graph is directed and if self loops are
5133 // allowed.
5134 // O(1).
5135 wgraph(int n, int m, bool is_directed = false, bool has_self_loops = false)
5136 : n_(n), m_(m), is_directed_(is_directed),
5137 has_self_loops_(has_self_loops) {
5138 tgen_ensure(n > 0, "wgraph: number of vertices must be positive");
5139 }
5140
5141 // Adds edge between u and v (this edge must be generated).
5142 // O(log m).
5143 wgraph &add_edge(int u, int v) {
5144 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,
5145 "wgraph: vertices must be indexed in [0, n)");
5146
5147 if (!is_directed_ and u > v)
5148 std::swap(u, v);
5149 edges_.emplace(u, v);
5150 tgen_ensure(static_cast<int>(edges_.size()) <= m_,
5151 "wgraph: too many edges were added");
5152 return *this;
5153 }
5154
5155 // Graph value.
5156 //
5157 // Edges are stored in both directions (if undirected) in adjacency list,
5158 // but only u < v in edge list.
5159 // Optimized for performance (lazy adjacency list; edge-list constructor
5160 // stores edges only).
5162 using std_type = std::tuple<int, int, std::vector<std::set<int>>>;
5163
5164 int n_; // Number of vertices.
5165 std::vector<std::set<int>> adj_; // Adjacency list.
5166 std::vector<std::pair<int, int>> edges_; // Edge list.
5167 bool is_directed_; // If graph is directed.
5168 bool add_1_; // If should add 1 for printing vertex ids.
5169 bool print_nm_; // If should print n and m.
5170 mutable bool adj_built_{
5171 false}; // Lazy cache: true once adj_ is built from edges_; mutable
5172 // so const adj() can populate it.
5173 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.
5174 std::optional<std::vector<EWeight>>
5175 edge_weights_; // Edge weights (in same order as edges_ ).
5176
5177 // Creates value from adjacency list. The edges
5178 // are considered to be directed.
5179 // O(n + m).
5180 value(const std::vector<std::set<int>> &adj, bool is_directed = false)
5181 : n_(static_cast<int>(adj.size())), adj_(adj),
5182 is_directed_(is_directed), add_1_(false), print_nm_(false),
5183 adj_built_(true) {
5184 for (int u = 0; u < n_; ++u)
5185 for (auto v : adj[u]) {
5187 0 <= v and v < n_,
5188 "wgraph: value: vertices must be indexed in [0, n)");
5189 // Undirected adjacency is symmetric: count each edge once
5190 // (canonical u <= v). Directed: every out-edge appears
5191 // once.
5192 if (is_directed_ or u <= v)
5193 edges_.emplace_back(u, v);
5194 }
5195 }
5196
5197 // Creates value from `n`, `m`, and edge list. The edges are
5198 // considered to be directed.
5199 // Optimized for performance (lazy adjacency list; unordered_set dedup).
5200 // O(m log m).
5201 value(int n, const std::vector<std::pair<int, int>> &edges = {},
5202 bool is_directed = false)
5203 : n_(n), edges_(), is_directed_(is_directed), add_1_(false),
5204 print_nm_(false), adj_built_(false) {
5205 edges_.reserve(edges.size());
5206 std::unordered_set<uint64_t> seen;
5207 seen.reserve(edges.size() * 2 + 1);
5208 for (auto [u, v] : edges) {
5210 0 <= std::min(u, v) and std::max(u, v) < n,
5211 "wgraph: value: vertices must be indexed in [0, n)");
5212 if (!is_directed_ and u > v)
5213 std::swap(u, v);
5214 uint64_t key = is_directed_ ? detail::directed_edge_key(u, v)
5215 : detail::undirected_edge_key(u, v);
5216 if (seen.insert(key).second)
5217 edges_.emplace_back(u, v);
5218 }
5219 }
5220 value(int n, const std::set<std::pair<int, int>> &edges,
5221 bool is_directed = false)
5222 : value(
5223 n,
5224 std::vector<std::pair<int, int>>(edges.begin(), edges.end()),
5225 is_directed) {}
5226 value(int n, const std::initializer_list<std::pair<int, int>> &edges,
5227 bool is_directed = false)
5228 : value(n, std::vector<std::pair<int, int>>(edges), is_directed) {}
5229
5230 // Creates graph from tree (undirected, same edges).
5231 // O(n).
5232 value(const typename wtree<VWeight, EWeight>::value &t)
5233 : value(t.n(), t.edges(), false) {
5234 if (t.vertex_weights().has_value()) {
5235 vertex_weights_ = *t.vertex_weights();
5236 }
5237 if (t.edge_weights().has_value()) {
5238 edge_weights_ = *t.edge_weights();
5239 }
5240 }
5241
5242 // Weight type conversion.
5243 // O(n + m).
5244 template <typename NewVWeight, typename NewEWeight>
5245 typename wgraph<NewVWeight, NewEWeight>::value
5246 convert_weight_types() const {
5247 tgen_ensure(!vertex_weights_.has_value() and
5248 !edge_weights_.has_value(),
5249 "wgraph: value: cannot convert weight type after "
5250 "assigning weights");
5251
5252 ensure_adj_built();
5253 typename wgraph<NewVWeight, NewEWeight>::value new_graph(
5254 adj_, is_directed_);
5255 new_graph.is_directed_ = is_directed_;
5256 new_graph.add_1_ = add_1_;
5257 new_graph.print_nm_ = print_nm_;
5258 return new_graph;
5259 }
5260
5261 // Fetches number of vertices.
5262 int n() const { return n_; }
5263
5264 // Fetches number of edges.
5265 int m() const { return edges_.size(); }
5266
5267 // Fetches if graph is directed;
5268 bool is_directed() const { return is_directed_; }
5269
5270 // Fetches a const ref. to adjacency list.
5271 const std::vector<std::set<int>> &adj() const {
5272 ensure_adj_built();
5273 return adj_;
5274 }
5275
5276 // Fetches a const ref. to edge set.
5277 const std::vector<std::pair<int, int>> &edges() const { return edges_; }
5278
5279 // Fetches vertex weights.
5281 return vertex_weights_;
5282 }
5283
5284 // Fetches edge weights.
5286 return edge_weights_;
5287 }
5288
5289 // Sets vertex weights.
5290 // O(n + m).
5291 template <typename NewVWeight = VWeight>
5292 typename wgraph<NewVWeight, EWeight>::value set_vertex_weights(
5293 const std::vector<NewVWeight> &vertex_weights) const {
5294 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),
5295 "wgraph: value: must give `n` vertex weights");
5296
5297 auto new_graph = convert_weight_types<NewVWeight, EWeight>();
5298 new_graph.vertex_weights_ = vertex_weights;
5299 return new_graph;
5300 }
5301
5302 // Sets edge weights.
5303 // O(n + m).
5304 template <typename NewEWeight = EWeight>
5305 typename wgraph<VWeight, NewEWeight>::value
5306 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {
5307 tgen_ensure(static_cast<int>(edge_weights.size()) == m(),
5308 "wgraph: value: must give `m` edge weights");
5309
5310 auto new_graph = convert_weight_types<VWeight, NewEWeight>();
5311 new_graph.edge_weights_ = edge_weights;
5312 return new_graph;
5313 }
5314
5315 // Enables edge-weighted mode before adding weighted edges
5316 // incrementally. The graph must have no edges yet. O(1).
5318 tgen_ensure(m() == 0,
5319 "wgraph: value: edge_weighted requires a graph with no "
5320 "edges");
5321 tgen_ensure(!edge_weights_.has_value(),
5322 "wgraph: value: graph is already edge-weighted");
5323
5324 edge_weights_ = std::vector<EWeight>();
5325 return *this;
5326 }
5327
5328 // Adds 1 to vertex ids, for printing.
5329 // O(1).
5331 add_1_ = true;
5332 return *this;
5333 }
5334
5335 // Prints `n m` on a new line before printing the edges.
5336 // O(1).
5338 print_nm_ = true;
5339 return *this;
5340 }
5341
5342 // Shuffles the graph's vertex labels (except those in `indices`,
5343 // which keep their current label) and edge order. The change is
5344 // applied eagerly to the underlying adjacency list, edge list,
5345 // vertex weights and edge weights.
5346 // O(n + m).
5347 value &shuffle_except(std::set<int> indices) {
5348 ensure_adj_built();
5349 // Builds the relabeling: for each vertex `i`, `new_label[i]` is
5350 // its new id. Vertices in `indices` keep their label; the others
5351 // are permuted among themselves.
5352 std::vector<int> new_label(n());
5353 std::vector<int> shuffled;
5354 for (int i = 0; i < n(); ++i) {
5355 if (indices.count(i))
5356 new_label[i] = i;
5357 else
5358 shuffled.push_back(i);
5359 }
5360 std::vector<int> targets = shuffled;
5361 tgen::shuffle(targets.begin(), targets.end());
5362 for (size_t k = 0; k < shuffled.size(); ++k)
5363 new_label[shuffled[k]] = targets[k];
5364
5365 // Rewrites adjacency list with new labels.
5366 std::vector<std::set<int>> new_adj(n());
5367 for (int u = 0; u < n(); ++u)
5368 for (int v : adj_[u])
5369 new_adj[new_label[u]].insert(new_label[v]);
5370 adj_ = new_adj;
5371
5372 // Rewrites edges with new labels (canonical undirected order).
5373 for (auto &[u, v] : edges_) {
5374 u = new_label[u];
5375 v = new_label[v];
5376 if (!is_directed_ and u > v)
5377 std::swap(u, v);
5378 }
5379
5380 // Permutes vertex weights to match the new labels.
5381 if (vertex_weights_.has_value()) {
5382 std::vector<VWeight> new_vw(n());
5383 for (int i = 0; i < n(); ++i)
5384 new_vw[new_label[i]] = (*vertex_weights_)[i];
5385 vertex_weights_ = new_vw;
5386 }
5387
5388 // Shuffles edge order, keeping edge weights aligned.
5389
5390 std::vector<int> perm(edges_.size());
5391 std::iota(perm.begin(), perm.end(), 0);
5392 tgen::shuffle(perm.begin(), perm.end());
5393
5394 std::vector<std::pair<int, int>> new_edges;
5395 std::optional<std::vector<EWeight>> new_ew;
5396 if (edge_weights_.has_value())
5397 new_ew = std::vector<EWeight>();
5398 for (int i : perm) {
5399 new_edges.push_back(edges_[i]);
5400 if (new_ew.has_value())
5401 new_ew->push_back((*edge_weights_)[i]);
5402 }
5403
5404 edges_ = new_edges;
5405 if (new_ew.has_value())
5406 edge_weights_ = new_ew;
5407
5408 return *this;
5409 }
5410
5411 // Shuffles the graph's vertices and edge order.
5412 // O(n + m).
5413 value &shuffle() { return shuffle_except({}); }
5414
5415 // Adds `k` vertices to the graph (labeled n, n+1, ...n+k-1). Updates
5416 // `n` accordingly.
5417 // O(k) amortized.
5418 value &add_vertices(int k, std::optional<std::vector<VWeight>>
5419 new_vertex_weights = std::nullopt) {
5420 ensure_adj_built();
5421 n_ += k;
5422 adj_.resize(n());
5423 if (new_vertex_weights.has_value()) {
5424 tgen_ensure(vertex_weights().has_value(),
5425 "wgraph: value: cannot add weighted vertices to "
5426 "vertex-unweighted graph");
5428 static_cast<int>(new_vertex_weights->size()) == k,
5429 "wgraph: value: number of vertex weights must be equal "
5430 "to number of added vertices");
5431
5432 vertex_weights_->insert(vertex_weights_->end(),
5433 new_vertex_weights->begin(),
5434 new_vertex_weights->end());
5435 } else
5436 tgen_ensure(!vertex_weights().has_value(),
5437 "wgraph: value: cannot add unweighted vertices to "
5438 "vertex-weighted graph");
5439
5440 return *this;
5441 }
5442
5443 // Adds edge (u, v).
5444 // O(log n) amortized.
5445 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {
5446 ensure_adj_built();
5447 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),
5448 "wgraph: value: vertex ids must be valid");
5449
5450 if (!is_directed() and u > v)
5451 std::swap(u, v);
5452
5453 if (adj_[u].count(v))
5454 return *this;
5455
5456 adj_[u].insert(v);
5457 if (!is_directed())
5458 adj_[v].insert(u);
5459 edges_.emplace_back(u, v);
5460
5461 if (w.has_value()) {
5462 tgen_ensure(edge_weights().has_value(),
5463 "wgraph: value: cannot add weighted edge to "
5464 "edge-unweighted graph");
5465
5466 edge_weights_->push_back(*w);
5467 } else
5468 tgen_ensure(!edge_weights().has_value(),
5469 "wgraph: value: cannot add unweighted edge to "
5470 "edge-weighted graph");
5471
5472 return *this;
5473 }
5474
5475 // Links graph with another `rhs`, adding the edge between u (in left
5476 // graph) and v (in right graph). Ids for added vertices are updated
5477 // accordingly.
5478 // O(rhs.n + rhs.m * log n) amortized.
5479 value &link(const value &rhs, int new_u, int new_v,
5480 std::optional<EWeight> new_w = std::nullopt) {
5481 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and
5482 new_v < rhs.n(),
5483 "wgraph: value: vertex ids must be valid");
5484
5485 // Edges from right-hand side.
5486 int shift = n();
5487 add_vertices(rhs.n(), rhs.vertex_weights());
5488 for (int i = 0; i < rhs.m(); ++i) {
5489 auto [u, v] = rhs.edges()[i];
5490 add_edge(shift + u, shift + v,
5491 rhs.edge_weights().has_value()
5492 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5493 : std::nullopt);
5494 }
5495
5496 // New edge.
5497 add_edge(new_u, shift + new_v, new_w);
5498
5499 return *this;
5500 }
5501
5502 // Glues the graph with another `rhs` such that index_pairs[i].first is
5503 // considered to be the same as index_pairs[i].second. Ids for added
5504 // vertices are updated accordingly.
5505 // O(rhs.n + rhs.m * log n) amortized.
5506 value &glue(const value &rhs,
5507 std::set<std::pair<int, int>> index_pairs) {
5510 "wgraph: value: graphs must have the same is_directed value");
5511
5512 // Checks validity of indices.
5513 std::set<int> idx_left, idx_right;
5514 std::vector<int> right_id_to_left(rhs.n(), -1);
5515 for (auto [l, r] : index_pairs) {
5517 0 <= l and l < n() and 0 <= r and r < rhs.n(),
5518 "wgraph: value: vertex indices to glue must be valid");
5519 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,
5520 "wgraph: value: must not have repeated indices "
5521 "on the same side to glue");
5522
5523 idx_left.insert(l);
5524 idx_right.insert(r);
5525 right_id_to_left[r] = l;
5526 }
5527
5528 // Computes new ids of right vertices.
5529 std::vector<int> new_right_id(rhs.n(), -1);
5530 int intersection_lt = 0;
5531 std::optional<std::vector<VWeight>> rhs_vertex_weights;
5532 for (int i = 0; i < rhs.n(); ++i) {
5533 if (right_id_to_left[i] != -1) {
5534 // Is in intersection.
5535 ++intersection_lt;
5536 new_right_id[i] = right_id_to_left[i];
5537 } else {
5538 // New id.
5539 new_right_id[i] = n() + i - intersection_lt;
5540 if (rhs.vertex_weights().has_value()) {
5541 if (!rhs_vertex_weights.has_value())
5542 rhs_vertex_weights = std::vector<VWeight>();
5543 rhs_vertex_weights->push_back(
5544 (*rhs.vertex_weights())[i]);
5545 }
5546 }
5547 }
5548
5549 // Adds new vertices and edges.
5550 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
5551 for (int i = 0; i < rhs.m(); ++i) {
5552 auto [u, v] = rhs.edges()[i];
5553 add_edge(new_right_id[u], new_right_id[v],
5554 rhs.edge_weights().has_value()
5555 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5556 : std::nullopt);
5557 }
5558
5559 return *this;
5560 }
5561 value &glue(const value &rhs,
5562 std::initializer_list<std::pair<int, int>> il) {
5563 return glue(rhs, std::set<std::pair<int, int>>(il));
5564 }
5565
5566 // Glues the graph with another `rhs` at `indices`. That is, idx in
5567 // `indices` are considered to be the same vertex. Ids for added
5568 // vertices are updated accordingly.
5569 // O(rhs.n + rhs.m * log n) amortized.
5570 value &glue(const value &rhs, std::set<int> indices) {
5571 std::set<std::pair<int, int>> index_pairs;
5572 for (auto i : indices)
5573 index_pairs.emplace(i, i);
5574 return glue(rhs, index_pairs);
5575 }
5576 value &glue(const value &rhs, const std::initializer_list<int> &il) {
5577 return glue(rhs, std::set<int>(il));
5578 }
5579
5580 // Disjoint union.
5581 // Shifts ids from `rhs` graph by n().
5582 // O(rhs.n + rhs.m * log n) amortized.
5584 return glue(rhs, std::set<int>());
5585 }
5586
5587 // Computes uniformly random subgraph of graph with num_edges edges.
5588 // O(n + m).
5589 value &random_subgraph(int num_edges) {
5591 num_edges <= m(),
5592 "wgraph: value: can choose at most `m` edges from graph");
5593
5594 std::vector<std::pair<int, int>> new_edges;
5595 std::optional<std::vector<EWeight>> new_edge_weights;
5596
5597 int left = m();
5598 for (int i = 0; i < m(); ++i) {
5599 if (next(1, left--) <= num_edges) {
5600 new_edges.push_back(edges()[i]);
5601 if (edge_weights_.has_value()) {
5602 if (!new_edge_weights.has_value())
5603 new_edge_weights = std::vector<EWeight>();
5604 new_edge_weights->push_back((*edge_weights())[i]);
5605 }
5606 --num_edges;
5607 }
5608 }
5609
5610 edges_ = new_edges;
5611 edge_weights_ = new_edge_weights;
5612 rebuild_adj_from_edge_list();
5613 return *this;
5614 }
5615
5616 // Computes a random (not uniform) subgraph with `num_edges` edges that
5617 // keeps every connected component connected (does not increase the
5618 // number of connected components).
5619 // 1. Picks a spanning forest via randomized Prim.
5620 // 2. Adds additional edges uniformly at random.
5621 // O(n + m).
5623 tgen_ensure(!is_directed_,
5624 "wgraph: value: random_connected_subgraph is only for "
5625 "undirected graphs");
5627 num_edges <= m(),
5628 "wgraph: value: can choose at most `m` edges from graph");
5629
5630 // Builds an incidence list: for each vertex, the (neighbor, edge
5631 // index) pairs.
5632 std::vector<std::vector<std::pair<int, int>>> incident(n());
5633 for (int i = 0; i < m(); ++i) {
5634 auto [u, v] = edges_[i];
5635 incident[u].emplace_back(v, i);
5636 incident[v].emplace_back(u, i);
5637 }
5638
5639 // Randomized Prim.
5640 std::vector<bool> vis(n(), false);
5641 std::vector<int> queue;
5642 std::vector<bool> in_tree(m(), false);
5643 int forest_edges = 0;
5644
5645 for (int start = 0; start < n(); ++start) {
5646 if (vis[start])
5647 continue;
5648 vis[start] = true;
5649 queue.push_back(start);
5650
5651 while (!queue.empty()) {
5652 int i = tgen::next<int>(0, queue.size() - 1);
5653 int u = queue[i];
5654 std::swap(queue[i], queue.back());
5655 queue.pop_back();
5656
5657 for (auto [v, edge_idx] : incident[u]) {
5658 if (!vis[v]) {
5659 vis[v] = true;
5660 queue.push_back(v);
5661 in_tree[edge_idx] = true;
5662 ++forest_edges;
5663 }
5664 }
5665 }
5666 }
5668 num_edges >= forest_edges,
5669 "wgraph: value: random_connected_subgraph needs at least "
5670 "`n - c` edges, where `c` is the number of connected "
5671 "components");
5672
5673 // Splits edge indices into forest edges and the rest.
5674 std::vector<int> tree_idx, rest_idx;
5675 for (int i = 0; i < m(); ++i) {
5676 if (in_tree[i])
5677 tree_idx.push_back(i);
5678 else
5679 rest_idx.push_back(i);
5680 }
5681
5682 tgen::shuffle(rest_idx.begin(), rest_idx.end());
5683
5684 std::vector<int> chosen_idx;
5685 chosen_idx.insert(chosen_idx.end(), tree_idx.begin(),
5686 tree_idx.end());
5687 chosen_idx.insert(chosen_idx.end(), rest_idx.begin(),
5688 rest_idx.begin() + num_edges - forest_edges);
5689
5690 detail::tgen_ensure_against_bug(
5691 static_cast<int>(chosen_idx.size()) == num_edges,
5692 "wgraph: value: chose a wrong number of edges");
5693
5694 std::vector<std::pair<int, int>> new_edges;
5695 std::optional<std::vector<EWeight>> new_edge_weights;
5696 if (edge_weights_.has_value())
5697 new_edge_weights = std::vector<EWeight>();
5698 for (int i : chosen_idx) {
5699 new_edges.push_back(edges_[i]);
5700 if (new_edge_weights.has_value())
5701 new_edge_weights->push_back((*edge_weights_)[i]);
5702 }
5703
5704 edges_ = new_edges;
5705 edge_weights_ = new_edge_weights;
5706 rebuild_adj_from_edge_list();
5707 return *this;
5708 }
5709
5710 // Complement. Self loops are maintained.
5711 // O(n^2).
5712 value operator!() const {
5713 tgen_ensure(!edge_weights_.has_value(),
5714 "wgraph: value: cannot compute complement of "
5715 "edge-weighted graph");
5716
5717 value complement = *this;
5718 complement.ensure_adj_built();
5719 std::vector<std::pair<int, int>> compl_edges;
5720 for (int i = 0; i < complement.n_; ++i) {
5721 std::set<int> complement_adj;
5722 for (int j = 0; j < complement.n_; ++j) {
5723 bool add_j = false;
5724 if (j == i and complement.adj_[i].count(j))
5725 add_j = true;
5726 if (j != i and !complement.adj_[i].count(j))
5727 add_j = true;
5728
5729 if (add_j) {
5730 complement_adj.insert(j);
5731 // If i > j and !is_directed(), we don't add the edge.
5732 if (i <= j or complement.is_directed_) {
5733 compl_edges.emplace_back(i, j);
5734 }
5735 }
5736 }
5737 std::swap(complement.adj_[i], complement_adj);
5738 }
5739 std::swap(complement.edges_, compl_edges);
5740
5741 return complement;
5742 }
5743
5744 // Concatenates two values.
5745 // O(N + M log N), N = n + rhs.n, M = m + rhs.m.
5746 value operator+(const value &rhs) const {
5748 "wgraph: value: graphs must have the same "
5749 "is_directed value");
5750
5751 tgen_ensure(vertex_weights().has_value() ==
5752 rhs.vertex_weights().has_value(),
5753 "wgraph: value: cannot concatenate vertex-weighted "
5754 "wgraph to unweighted");
5755 tgen_ensure(edge_weights().has_value() ==
5756 rhs.edge_weights().has_value(),
5757 "wgraph: value: cannot concatenate edge-weighted "
5758 "wgraph to unweighted");
5759
5760 value concat = *this;
5761 concat.glue(rhs, std::set<std::pair<int, int>>());
5762 concat.add_1_ = add_1_ | rhs.add_1_;
5763 concat.print_nm_ = print_nm_ | rhs.print_nm_;
5764
5765 return concat;
5766 }
5767
5768 // Prints to std::ostream.
5769 // O(n + m).
5770 friend std::ostream &operator<<(std::ostream &out, const value &val) {
5771 // Prints `n` and `m`.
5772 if (val.print_nm_)
5773 out << val.n() << " " << val.m() << '\n';
5774
5775 // Prints vertex weights.
5776 if (val.vertex_weights()) {
5777 for (int i = 0; i < val.n(); ++i) {
5778 if (i > 0)
5779 out << " ";
5780 out << (*val.vertex_weights())[i];
5781 }
5782 out << '\n';
5783 }
5784
5785 // Prints edges.
5786 for (int i = 0; i < val.m(); ++i) {
5787 auto [u, v] = val.edges()[i];
5788 out << (u + val.add_1_) << " " << (v + val.add_1_);
5789
5790 // Edge weight.
5791 if (val.edge_weights().has_value())
5792 out << " " << (*val.edge_weights())[i];
5793
5794 out << '\n';
5795 }
5796
5797 return out;
5798 }
5799
5800 // Gets a std::tuple<n, m, adj> representing the value.
5801 std::tuple<int, int, std::vector<std::set<int>>> to_std() const {
5802 ensure_adj_built();
5803 return std_type(n_, m(), adj_);
5804 }
5805
5806 private:
5807 // Rebuilds adjacency from edges_ after replacing the edge list (e.g.
5808 // subgraph operations).
5809 // O(m log n).
5810 void rebuild_adj_from_edge_list() {
5811 adj_.assign(n_, {});
5812 for (auto [u, v] : edges_) {
5813 adj_[u].insert(v);
5814 if (!is_directed_)
5815 adj_[v].insert(u);
5816 }
5817 adj_built_ = true;
5818 }
5819
5820 // Builds adj_ from edges_ on first use.
5821 // O(1) if already built; O(m log n) otherwise.
5822 void ensure_adj_built() const {
5823 if (adj_built_)
5824 return;
5825 const_cast<value *>(this)->rebuild_adj_from_edge_list();
5826 }
5827 };
5828
5829 // Adds all edges from `rhs` as preset edges.
5830 // O(rhs.m * log m).
5832 tgen_ensure(is_directed_ == rhs.is_directed(),
5833 "wgraph: graphs must have the same is_directed value");
5834
5835 for (auto [u, v] : rhs.edges())
5836 add_edge(u, v);
5837 return *this;
5838 }
5839
5840 // Generates graph value.
5841 // Optimized for performance: dense no-preset graphs use index sampling;
5842 // otherwise gen_remaining_edges.
5843 // O(n + m log^2 n) expected.
5844 value gen() const {
5845 detail::tgen_ensure_against_bug(static_cast<int>(edges_.size()) <= m_,
5846 "wgraph: too many edges were added");
5847
5848 // All edges already added.
5849 if (static_cast<int>(edges_.size()) == m_)
5850 return value(n_, edges_, is_directed_);
5851
5852 // Splits into two cases to optimize performance.
5853
5854 // No presets and m > max_edges / 2: sample m distinct edge indices.
5855 if (auto indexed = try_gen_by_edge_index())
5856 return *indexed;
5857
5858 // Otherwise: fill preset edges up to m_ with uniform random edges.
5859 return gen_remaining_edges(
5860 std::vector<std::pair<int, int>>(edges_.begin(), edges_.end()));
5861 }
5862
5863 // Gets a (not uniformly) random connected undirected graph.
5864 // 1. Preset edges induce a spanning forest on their components.
5865 // 2. Then, uniformly random edges between components are added.
5866 // 3. Remaining edges are added uniformly at random.
5867 // O(n + m log^2 n) expected.
5869 tgen_ensure(!is_directed_,
5870 "wgraph: get_connected is only for undirected graphs");
5871 tgen_ensure(m_ >= n_ - 1,
5872 "wgraph: connected graph needs at least n - 1 edges");
5873
5874 std::vector<std::pair<int, int>> edges;
5875 edges.reserve(m_);
5876
5877 if (edges_.empty()) {
5878 if (n_ > 1) {
5879 std::vector<int> prufer(n_ - 2);
5880 for (int i = 0; i < n_ - 2; ++i)
5881 prufer[i] = next<int>(0, n_ - 1);
5882 for (auto [u, v] : detail::edges_from_prufer(std::move(prufer)))
5883 edges.emplace_back(u, v);
5884 }
5885 } else {
5886 edges.assign(edges_.begin(), edges_.end());
5887
5888 std::vector<std::vector<int>> adj(n_);
5889 for (auto [u, v] : edges_) {
5890 adj[u].push_back(v);
5891 adj[v].push_back(u);
5892 }
5893
5894 std::vector<int> comp_size;
5895 std::vector<std::vector<int>> component_ids;
5896 std::vector<bool> vis(n_, false);
5897 std::queue<int> q;
5898
5899 for (int i = 0; i < n_; ++i) {
5900 if (vis[i])
5901 continue;
5902
5903 vis[i] = true;
5904 q.push(i);
5905 comp_size.push_back(0);
5906 component_ids.emplace_back();
5907 while (q.size()) {
5908 int u = q.front();
5909 q.pop();
5910 ++comp_size.back();
5911 component_ids.back().push_back(u);
5912 for (int v : adj[u]) {
5913 if (!vis[v]) {
5914 vis[v] = true;
5915 q.push(v);
5916 }
5917 }
5918 }
5919 }
5920
5921 if (component_ids.size() > 1) {
5922 std::vector<int> prufer_values =
5923 many_by_distribution(component_ids.size() - 2, comp_size);
5924 for (auto [u, v] :
5925 detail::edges_from_prufer(std::move(prufer_values)))
5926 edges.emplace_back(pick(component_ids[u]),
5927 pick(component_ids[v]));
5928 }
5929 }
5930
5931 return gen_remaining_edges(std::move(edges));
5932 }
5933
5934 // Gets a (not uniformly) random directed acyclic graph.
5935 // 1. Randomized Kahn (uniform choice among indegree-0 vertices) yields a
5936 // random topological order of the preset edges (which must be acyclic).
5937 // 2. Extra edges are sampled randomly using the order.
5938 // With no preset edges: sample a random graph then orient acyclically.
5939 // Optimized for performance (distinct upper-triangle edge-index sampling;
5940 // rejection instead of pair::distinct for preset edges).
5941 // O(n + m log^2 n) expected.
5943 tgen_ensure(is_directed_,
5944 "wgraph: get_acyclic is only for directed graphs");
5945
5946 if (edges_.empty()) {
5947 std::vector<int> order(n_);
5948 std::iota(order.begin(), order.end(), 0);
5949 for (int i = n_ - 1; i > 0; --i)
5950 std::swap(order[i], order[next(0, i)]);
5951
5952 const long long max_pairs =
5953 static_cast<long long>(n_) * (n_ - 1) / 2;
5954 tgen_ensure(m_ <= max_pairs,
5955 "wgraph: not enough edges to generate");
5956
5957 std::vector<std::pair<int, int>> edges;
5958 edges.reserve(m_);
5959 for (long long idx : distinct_range<long long>(0, max_pairs - 1)
5960 .gen_list(m_)
5961 .to_std()) {
5962 auto [i, j] = detail::decode_undirected_simple_edge(n_, idx);
5963 edges.emplace_back(order[i], order[j]);
5964 }
5965 return value(n_, edges, true);
5966 }
5967
5968 std::vector<std::vector<int>> adj(n_);
5969 std::vector<int> indeg(n_, 0);
5970 for (auto [u, v] : edges_) {
5971 adj[u].push_back(v);
5972 ++indeg[v];
5973 }
5974
5975 std::vector<int> available;
5976 for (int i = 0; i < n_; ++i)
5977 if (indeg[i] == 0)
5978 available.push_back(i);
5979
5980 // Random topological order using randomized Kahn's algorithm.
5981 std::vector<int> order;
5982 while (!available.empty()) {
5983 int idx = next(0, static_cast<int>(available.size()) - 1);
5984 int u = available[idx];
5985 std::swap(available[idx], available.back());
5986 available.pop_back();
5987
5988 order.push_back(u);
5989 for (int v : adj[u])
5990 if (--indeg[v] == 0)
5991 available.push_back(v);
5992 }
5993
5994 tgen_ensure(static_cast<int>(order.size()) == n_,
5995 "wgraph: preset edges contain a directed cycle");
5996
5997 value acyclic(n_, edges_, true);
5998
5999 // Generates final edges.
6000
6001 detail::tgen_ensure_against_bug(acyclic.m() <= m_,
6002 "wgraph: too many edges were added");
6003
6004 if (acyclic.m() < m_) {
6005 std::vector<int> order_pos(n_);
6006 for (int i = 0; i < n_; ++i)
6007 order_pos[order[i]] = i;
6008
6009 std::unordered_set<uint64_t> seen;
6010 seen.reserve(m_ * 2);
6011 for (auto [u, v] : acyclic.edges())
6012 seen.insert(
6013 detail::undirected_edge_key(order_pos[u], order_pos[v]));
6014
6015 const long long max_pairs =
6016 static_cast<long long>(n_) * (n_ - 1) / 2;
6017 while (acyclic.m() < m_) {
6018 std::pair<int, int> edge;
6019 if (!detail::try_generate_distinct(seen, [&] {
6020 long long idx = next<long long>(0, max_pairs - 1);
6021 edge = detail::decode_undirected_simple_edge(n_, idx);
6022 return detail::undirected_edge_key(edge.first,
6023 edge.second);
6024 }))
6025 throw detail::error("wgraph: not enough edges to generate");
6026 acyclic.add_edge(order[edge.first], order[edge.second]);
6027 }
6028 }
6029
6030 return acyclic;
6031 }
6032
6033 // Generates a (not uniformly) random skewed connected graph.
6034 // 1. Builds the same skewed labeled tree as wtree::gen_skewed(n,
6035 // elongation)(root 0, parent(i) = wnext(i, elongation) for i >= 1).
6036 // If is_directed, tree edges are oriented down the tree.
6037 // 2. Adds the remaining edges: pick an endpoint u uniformly;
6038 // pick k uniformly in [1, spread]; walk from u toward the root k
6039 // times along tree parents to get v; add edge (v, u).
6040 // If elongation is small, generates a graph with small diameter.
6041 // If elongation is large, generates a graph with large diameter, with
6042 // vertices 0 and n-1 being far apart.
6043 // O(n + m log n) if spread is O(1);
6044 // O(n log n + m log^2 n) expected otherwise.
6045 static value gen_skewed(int n, int m, int elongation, int spread,
6046 bool is_directed = false) {
6048 m >= n - 1,
6049 "wgraph: skewed graph needs at least n - 1 edges to be connected");
6050 tgen_ensure(spread >= 2,
6051 "wgraph: gen_skewed spread must be at least 2");
6052
6053 value skewed(n, {}, is_directed);
6054
6055 std::vector<int> parent(n), depth(n, 0);
6056 parent[0] = 0;
6057 for (int i = 1; i < n; ++i) {
6058 int p = wnext<int>(i, elongation);
6059 parent[i] = p;
6060 depth[i] = depth[p] + 1;
6061 skewed.add_edge(p, i);
6062 }
6063
6064 const int extra = m - (n - 1);
6065 if (extra == 0)
6066 return skewed;
6067
6068 // If spread is large, use binary lifting to find the ancestor.
6069 // Otherwise, enumerate O(n * spread) ancestor edges and sample
6070 // directly.
6071 constexpr int naive_ancestor_spread = 20;
6072
6073 if (spread <= naive_ancestor_spread) {
6074 std::vector<std::pair<int, int>> candidates;
6075 candidates.reserve(n * spread);
6076 for (int u = 0; u < n; ++u) {
6077 int max_k = std::min(spread, depth[u]);
6078 if (max_k < 2)
6079 continue;
6080 int v = parent[u];
6081 for (int k = 2; k <= max_k; ++k) {
6082 v = parent[v];
6083 candidates.emplace_back(v, u);
6084 }
6085 }
6086
6087 tgen_ensure(extra <= static_cast<int>(candidates.size()),
6088 "wgraph: not enough edges to generate");
6089
6090 for (auto [v, u] : choose(candidates, extra))
6091 skewed.add_edge(v, u);
6092 } else {
6093 // Binary lifting.
6094 int lg = 1;
6095 while ((1 << lg) <= n)
6096 ++lg;
6097
6098 std::vector<std::vector<int>> up(lg, std::vector<int>(n));
6099 for (int v = 0; v < n; ++v)
6100 up[0][v] = parent[v];
6101 for (int j = 1; j < lg; ++j)
6102 for (int v = 0; v < n; ++v)
6103 up[j][v] = up[j - 1][up[j - 1][v]];
6104
6105 // Creates uniform generator of edges (u, v) such that v is ancestor
6106 // of u. For that, every u has depth[u]-1 choices for v, so we
6107 // weight u by min(spread - 1, depth[u] - 1). After that we can
6108 // just pick the ancestor uniformly.
6109 std::vector<int> distribution = depth;
6110 for (int &d : distribution)
6111 d = std::max(0, std::min(spread - 1, d - 1));
6112 weighted_sampler vertex_choice(distribution);
6113 distinct extra_edges([&]() -> std::pair<int, int> {
6114 int u = vertex_choice.next();
6115 int k = next(2, spread);
6116 int v = u;
6117 for (int j = 0; j < lg; ++j)
6118 if (k >> j & 1)
6119 v = up[j][v];
6120 return {v, u};
6121 });
6122
6123 while (skewed.m() < m) {
6124 std::pair<int, int> edge;
6125 try {
6126 edge = extra_edges.gen();
6127 } catch (const std::runtime_error &e) {
6128 if (std::string(e.what()) ==
6129 "tgen: distinct: no more distinct values")
6130 throw detail::error(
6131 "wgraph: not enough edges to generate");
6132 throw e;
6133 }
6134
6135 skewed.add_edge(edge.first, edge.second);
6136 }
6137 }
6138
6139 return skewed;
6140 }
6141
6142 // Generates a random bipartite graph. The first side has vertices
6143 // 0 .. n1-1, the second n1 .. n1+n2-1.
6144 // Uniform when connected is false (distinct cross-edge indices).
6145 // When connected, bipartite Prüfer + rejection fill; not uniform over
6146 // connected bipartite graphs.
6147 // O(n1 + n2 + m log(n1 * n2)) expected.
6148 static value gen_bipartite(int n1, int n2, int m, bool connected = false) {
6149 tgen_ensure(m >= 0, "wgraph: number of edges must be nonnegative");
6150 long long num_edges = 1LL * n1 * n2;
6151 tgen_ensure(m <= num_edges,
6152 "wgraph: bipartite graph has at most n1 * n2 edges");
6153 if (connected)
6155 m >= n1 + n2 - 1,
6156 "wgraph: connected bipartite graph needs at least n1 + n2 - 1 "
6157 "edges");
6158
6159 if (!connected) {
6160 std::vector<std::pair<int, int>> edges;
6161 edges.reserve(m);
6162 for (long long idx : distinct_range<long long>(0, num_edges - 1)
6163 .gen_list(m)
6164 .to_std())
6165 edges.emplace_back(static_cast<int>(idx / n2),
6166 n1 + static_cast<int>(idx % n2));
6167 return value(n1 + n2, std::move(edges), false);
6168 }
6169
6170 std::unordered_set<uint64_t> used_edges;
6171 used_edges.reserve(m * 2);
6172 std::vector<std::pair<int, int>> edges;
6173 edges.reserve(m);
6174
6175 auto pack_edge = [](int u, int v) -> uint64_t {
6176 if (u > v)
6177 std::swap(u, v);
6178 return (static_cast<uint64_t>(u) << 32) | static_cast<uint32_t>(v);
6179 };
6180
6181 if (n1 > 0 and n2 > 0) {
6182 std::vector<int> prufer(n1 + n2 - 2);
6183 for (int i = 0; i < n2 - 1; ++i)
6184 prufer[i] = next(0, n1 - 1);
6185 for (int i = 0; i < n1 - 1; ++i)
6186 prufer[n2 - 1 + i] = next(n1, n1 + n2 - 1);
6187 shuffle(prufer.begin(), prufer.end());
6188 for (auto [u, v] : detail::edges_from_prufer(std::move(prufer))) {
6189 if (u > v)
6190 std::swap(u, v);
6191 if (used_edges.insert(pack_edge(u, v)).second)
6192 edges.emplace_back(u, v);
6193 }
6194 detail::tgen_ensure_against_bug(
6195 used_edges.size() == size_t(n1 + n2 - 1),
6196 "wgraph: invalid bipartite spanning tree size");
6197 }
6198
6199 while (edges.size() < size_t(m)) {
6200 int u = next(0, n1 - 1);
6201 int v = next(n1, n1 + n2 - 1);
6202 if (used_edges.insert(pack_edge(u, v)).second)
6203 edges.emplace_back(u, v);
6204 }
6205
6206 return value(n1 + n2, std::move(edges), false);
6207 }
6208
6209 private:
6210 // If this generator has no preset edges and m is large relative to the
6211 // maximum edge count, sample by distinct edge index. Otherwise
6212 // std::nullopt.
6213 // Optimized for performance (index sampling instead of rejection).
6214 // O(m log n).
6215 std::optional<value> try_gen_by_edge_index() const {
6216 if (!edges_.empty())
6217 return std::nullopt;
6218
6219 long long max_edges =
6220 detail::max_graph_edges(n_, is_directed_, has_self_loops_);
6221 if (m_ > max_edges)
6222 throw detail::error("wgraph: not enough edges to generate");
6223 if (max_edges <= 0 or 2LL * m_ <= max_edges)
6224 return std::nullopt;
6225
6226 std::vector<std::pair<int, int>> edges;
6227 edges.reserve(m_);
6228 for (long long idx :
6229 distinct_range<long long>(0, max_edges - 1).gen_list(m_).to_std())
6230 edges.push_back(detail::decode_graph_edge_index(
6231 n_, idx, is_directed_, has_self_loops_));
6232
6233 return value(n_, edges, is_directed_);
6234 }
6235
6236 // Fills `edges` up to m_ with uniform random edges not already present.
6237 // Optimized for performance (uint64 edge keys + try_generate_distinct).
6238 // O(m log^2 n) expected.
6239 value gen_remaining_edges(std::vector<std::pair<int, int>> edges) const {
6240 detail::tgen_ensure_against_bug(static_cast<int>(edges.size()) <= m_,
6241 "wgraph: too many edges were added");
6242
6243 if (static_cast<int>(edges.size()) == m_)
6244 return value(n_, edges, is_directed_);
6245
6246 edges.reserve(m_);
6247
6248 std::unordered_set<uint64_t> seen;
6249 seen.reserve(m_ * 2);
6250 for (auto [u, v] : edges) {
6251 if (!is_directed_ and u > v)
6252 std::swap(u, v);
6253 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)
6254 : detail::undirected_edge_key(u, v));
6255 }
6256
6257 while (static_cast<int>(edges.size()) < m_) {
6258 std::pair<int, int> edge;
6259 if (!detail::try_generate_distinct(seen, [&] {
6260 edge = detail::get_random_graph_edge(n_, is_directed_,
6261 has_self_loops_);
6262 if (!is_directed_ and edge.first > edge.second)
6263 std::swap(edge.first, edge.second);
6264 return is_directed_ ? detail::directed_edge_key(edge.first,
6265 edge.second)
6266 : detail::undirected_edge_key(
6267 edge.first, edge.second);
6268 }))
6269 throw detail::error("wgraph: not enough edges to generate");
6270 edges.emplace_back(edge);
6271 }
6272
6273 return value(n_, edges, is_directed_);
6274 }
6275};
6276
6277// Implementation of wtree::value constructor from wgraph.
6278// O(n + m alpha(n)).
6279template <typename VWeight, typename EWeight>
6280wtree<VWeight, EWeight>::value::value(
6281 const typename wgraph<VWeight, EWeight>::value &g)
6282 : n_(g.n()), adj_(g.n()), add_1_(false), print_n_(false), dsu_(g.n()) {
6283 tgen_ensure(g.n() > 0, "wtree: value: graph must have at least one vertex");
6284 tgen_ensure(!g.is_directed(),
6285 "wtree: value: graph must be undirected to form a tree");
6286
6287 if (g.vertex_weights().has_value())
6288 vertex_weights_ = *g.vertex_weights();
6289 if (g.edge_weights().has_value())
6290 edge_weights_ = std::vector<EWeight>();
6291
6292 if (n_ == 1)
6293 return;
6294
6295 std::vector<int> order(g.m());
6296 std::iota(order.begin(), order.end(), 0);
6297 tgen::shuffle(order.begin(), order.end());
6298
6299 std::vector<std::pair<int, int>> tree_edges;
6300 tree_edges.reserve(n_ - 1);
6301
6302 for (int i : order) {
6303 auto [u, v] = g.edges()[i];
6304 if (!dsu_.unite(u, v))
6305 continue;
6306 if (u > v)
6307 std::swap(u, v);
6308
6309 tree_edges.emplace_back(u, v);
6310 adj_[u].insert(v);
6311 adj_[v].insert(u);
6312 if (edge_weights_.has_value())
6313 edge_weights_->push_back((*g.edge_weights())[i]);
6314 if (static_cast<int>(tree_edges.size()) == n_ - 1)
6315 break;
6316 }
6317
6318 tgen_ensure(static_cast<int>(tree_edges.size()) == n_ - 1,
6319 "wtree: value: graph must be connected to form a tree");
6320
6321 edges_ = std::move(tree_edges);
6322}
6323
6324/*
6325 * Other types of weighted-ness.
6326 */
6327
6328// Vertex weighted graph.
6329template <typename VWeight> using vgraph = wgraph<VWeight, int>;
6330
6331// Edge weighted graph.
6332template <typename EWeight> using egraph = wgraph<int, EWeight>;
6333
6334// Unweighted graph.
6335using graph = wgraph<int, int>;
6336
6337/*
6338 * Standard graphs.
6339 */
6340
6341// Complete.
6342// O(n^2).
6343inline graph::value K(int n) { return graph(n, n * (n - 1) / 2).gen(); }
6344
6345// Path.
6346// Path with `n` vertices. The edges of the path are 0 and n-1.
6347// If directed, edges are i -> i+1 for i in [0, n-2).
6348// O(n).
6349inline graph::value P(int n, bool is_directed = false) {
6350 graph g(n, n - 1, is_directed);
6351 for (int i = 0; i + 1 < n; ++i)
6352 g.add_edge(i, i + 1);
6353 return g.gen();
6354}
6355
6356// Cycle.
6357// n >= 3.
6358// If directed, edges are i -> (i+1) % n.
6359// O(n).
6360inline graph::value C(int n, bool is_directed = false) {
6361 tgen_ensure(n >= 3, "graph: cycle size must be at least 3");
6362
6363 graph g(n, n, is_directed);
6364 for (int i = 0; i < n; ++i)
6365 g.add_edge(i, (i + 1) % n);
6366 return g.gen();
6367}
6368
6369// Complete bipartite.
6370// The first side has vertices `0` to `n1-1`, the second side has vertices `n1`
6371// to `n1+n2-1`.
6372// O(n1 * n2).
6373inline graph::value K(int n1, int n2) {
6374 graph g(n1 + n2, static_cast<long long>(n1) * n2);
6375 for (int i = 0; i < n1; ++i)
6376 for (int j = 0; j < n2; ++j)
6377 g.add_edge(i, n1 + j);
6378 return g.gen();
6379}
6380
6381// Star.
6382// The center is vertex 0.
6383// O(n).
6384inline graph::value S(int n) { return K(1, n - 1); }
6385
6386/****************
6387 * *
6388 * GEOMETRY *
6389 * *
6390 ****************/
6391
6392namespace geometry {
6393
6394// Point on the plane with coordinates of type T.
6395template <typename T> struct point {
6396 static_assert(std::is_arithmetic_v<T>,
6397 "point requires an arithmetic coordinate type");
6398
6399 // Dot/cross product type: __int128 for T = long long, long long for other
6400 // integral T, T for floating-point.
6401 using product_t = std::conditional_t<
6402 std::is_same_v<T, long long>, detail::i128,
6403 std::conditional_t<std::is_integral_v<T>, long long, T>>;
6404
6405 // x and y coordinates.
6406 T x_, y_;
6407
6408 // Constructs a point with coordinates x and y.
6409 point(T x = 0, T y = 0) : x_(x), y_(y) {}
6410
6411 // Returns the x coordinate.
6412 T x() const { return x_; }
6413
6414 // Returns the y coordinate.
6415 T y() const { return y_; }
6416
6417 // Equality of coordinates, with epsilon-based equality for floating-point
6418 // coordinates (tolerance 1e-9).
6419 static bool coord_eq(T a, T b) {
6420 if constexpr (std::is_integral_v<T>)
6421 return a == b;
6422 constexpr T eps = T(1e-9);
6423 T d = a - b;
6424 return d >= -eps and d <= eps;
6425 }
6426
6427 // Lexicographic order (by x, then y).
6428 bool operator<(const point &p) const {
6429 if (!coord_eq(x_, p.x()))
6430 return x_ < p.x();
6431 return y_ < p.y();
6432 }
6433
6434 // Equality of coordinates.
6435 bool operator==(const point &p) const {
6436 return coord_eq(x_, p.x()) and coord_eq(y_, p.y());
6437 }
6438
6439 // Vector addition.
6440 point operator+(const point &p) const {
6441 return point(x_ + p.x(), y_ + p.y());
6442 }
6443
6444 // Vector subtraction.
6445 point operator-(const point &p) const {
6446 return point(x_ - p.x(), y_ - p.y());
6447 }
6448
6449 // Scalar multiplication.
6450 point operator*(T c) const { return point(x_ * c, y_ * c); }
6451
6452 // Dot product.
6453 product_t operator*(const point &p) const {
6454 if constexpr (std::is_floating_point_v<T>)
6455 return x_ * p.x() + y_ * p.y();
6456 return product_t(x_) * p.x() + product_t(y_) * p.y();
6457 }
6458
6459 // Cross product (signed area of the parallelogram).
6460 product_t operator^(const point &p) const {
6461 if constexpr (std::is_floating_point_v<T>)
6462 return x_ * p.y() - y_ * p.x();
6463 return product_t(x_) * p.y() - product_t(y_) * p.x();
6464 }
6465
6466 // Prints the point as "x y".
6467 friend std::ostream &operator<<(std::ostream &out, const point &p) {
6468 return out << p.x() << ' ' << p.y();
6469 }
6470};
6471
6472// Generates n distinct integer points in [min_coord, max_coord]^2 with no three
6473// collinear.
6474// O(n).
6475inline std::vector<point<long long>>
6476random_points_general_position(int n, long long min_coord,
6477 long long max_coord) {
6478 tgen_ensure(n > 0,
6479 "geometry: random_points_general_position: n must be positive");
6480 tgen_ensure(max_coord >= min_coord,
6481 "geometry: random_points_general_position: min_coord must be "
6482 "at most max_coord");
6484 static_cast<detail::i128>(max_coord) - min_coord <=
6485 std::numeric_limits<long long>::max(),
6486 "geometry: random_points_general_position: coordinate range too large");
6487 uint64_t width = max_coord - min_coord;
6488 uint64_t p = math::prime_from(2 * n);
6489
6490 // Requires width >= p - 1 because sheared coordinates lie in [0, p - 1].
6491 tgen_ensure(width >= p - 1,
6492 "geometry: random_points_general_position: coordinate range "
6493 "too small for n");
6494
6495 // Base set: (x, x^-1 mod p) for x = 1, ..., p - 1.
6496 //
6497 // For a line ax + by + c = 0, substituting y = x^-1 gives ax^2 + cx + b = 0
6498 // (for x != 0), a quadratic with at most two roots in F_p. So at most two
6499 // base points lie on any line. x |-> x^-1 is bijective on {1, ..., p - 1},
6500 // so all points are distinct and no three are collinear.
6501 std::vector<uint64_t> x_range(p - 1);
6502 std::iota(x_range.begin(), x_range.end(), 1);
6503 shuffle(x_range.begin(), x_range.end());
6504 std::vector<detail::i128> bx(n), by(n);
6505 for (int i = 0; i < n; ++i) {
6506 uint64_t x = x_range[i];
6507 bx[i] = x;
6508 by[i] = math::modular_inverse(x, p);
6509 }
6510
6511 // Randomize placement without breaking general position: compose elementary
6512 // shears in SL(2, F_p), each either [1 r; 0 1] or [1 0; r 1] with
6513 // r in {-2, -1, 1, 2} (mod p). Every shear has determinant 1, so their
6514 // product is invertible. Invertible linear maps preserve collinearity, so
6515 // the image still has no three collinear points.
6516 const int num_shears = 8;
6517 std::vector<detail::i128> lin_x = bx, lin_y = by;
6518
6519 for (int it = 0; it < num_shears; ++it) {
6520 bool vertical_shear = next(2) == 0;
6521 int shear_r = pick({-2, -1, 1, 2});
6522
6523 for (int i = 0; i < n; ++i) {
6524 if (vertical_shear)
6525 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;
6526 else
6527 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;
6528
6529 if (lin_x[i] < 0)
6530 lin_x[i] += p;
6531 if (lin_y[i] < 0)
6532 lin_y[i] += p;
6533 }
6534 }
6535
6536 detail::i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0],
6537 max_y = lin_y[0];
6538 for (int i = 1; i < n; ++i) {
6539 min_x = std::min(min_x, lin_x[i]);
6540 max_x = std::max(max_x, lin_x[i]);
6541 min_y = std::min(min_y, lin_y[i]);
6542 max_y = std::max(max_y, lin_y[i]);
6543 }
6544
6545 long long x_shift =
6546 min_coord - min_x + next<long long>(0, width - (max_x - min_x));
6547 long long y_shift =
6548 min_coord - min_y + next<long long>(0, width - (max_y - min_y));
6549
6550 std::vector<point<long long>> pts;
6551 for (int i = 0; i < n; ++i)
6552 pts.emplace_back(lin_x[i] + x_shift, lin_y[i] + y_shift);
6553 return pts;
6554}
6555
6556namespace detail {
6557
6558using i128 = tgen::detail::i128;
6559
6560// Signed area of triangle (a, b, p); positive iff (a, b, p) are in
6561// counterclockwise order. 0 iff (a, b, p) are collinear. O(1).
6562inline i128 ccw(const point<long long> &a, const point<long long> &b,
6563 const point<long long> &p) {
6564 return (static_cast<i128>(b.x()) - a.x()) *
6565 (static_cast<i128>(p.y()) - a.y()) -
6566 (static_cast<i128>(b.y()) - a.y()) *
6567 (static_cast<i128>(p.x()) - a.x());
6568}
6569
6570// Integer projection of P onto line AB (A and B need not be distinct).
6571inline i128 proj_on_ab(const point<long long> &P, const point<long long> &A,
6572 const point<long long> &B) {
6573 return (P - A) * (B - A);
6574}
6575
6576// In-place Hamiltonian path on points[left..right-1] with points[left]
6577// start and points[right-1] end.
6578// O(n log n) expected if points are "random", O(n^2) worst case.
6579inline void conquer(std::vector<point<long long>> &points, int left,
6580 int right) {
6581 if (right - left <= 3)
6582 return;
6583
6584 point<long long> A = points[left], B = points[right - 1];
6585
6586 // If all points are collinear, sort them properly and return.
6587 bool all_collinear = true;
6588 for (int k = left + 1; k < right - 1; ++k) {
6589 if (ccw(A, B, points[k]) != 0) {
6590 all_collinear = false;
6591 break;
6592 }
6593 }
6594 if (all_collinear) {
6595 std::sort(points.begin() + left, points.begin() + right,
6596 [&](const point<long long> &P, const point<long long> &Q) {
6597 return proj_on_ab(P, A, B) < proj_on_ab(Q, A, B);
6598 });
6599 return;
6600 }
6601
6602 // Choses a pivot that is not collinear with A and B.
6603 std::vector<int> candidates;
6604 for (int k = left + 1; k < right - 1; ++k) {
6605 if (ccw(A, B, points[k]) != 0)
6606 candidates.push_back(k);
6607 }
6608 int ci = candidates[next(0, static_cast<int>(candidates.size()) - 1)];
6609 point<long long> C = points[ci];
6610
6611 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6612 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6613 bool a_on_positive = ccw(C, A, B) < 0;
6614
6615 // Classify interior points into two sides of the wedge A-C-B for partition.
6616 // Collinear points on AB are tie-broken along the segment.
6617 i128 proj_sum = proj_on_ab(A, A, B) + proj_on_ab(B, A, B);
6618 auto is_positive = [&](const point<long long> &P) -> bool {
6619 i128 s = wa * ccw(C, A, P) + wb * ccw(C, B, P);
6620 // Weighted wedge side of P w.r.t. C, A, B.
6621 if (s != 0)
6622 return s > 0;
6623 // P is on line AB: split by projection past the midpoint.
6624 return 2 * proj_on_ab(P, A, B) > proj_sum;
6625 };
6626
6627 // Holds C at points[right-2] while classifying interior points in
6628 // [left+1, right-3].
6629 if (ci != right - 2)
6630 std::swap(points[ci], points[right - 2]);
6631
6632 int i = left + 1;
6633 int j = right - 3;
6634 while (i < j) {
6635 if (is_positive(points[i]) == a_on_positive)
6636 ++i;
6637 else if (is_positive(points[j]) != a_on_positive)
6638 --j;
6639 else {
6640 std::swap(points[i], points[j]);
6641 ++i;
6642 --j;
6643 }
6644 }
6645
6646 // After partition:
6647 // points[left]=A | (A,C)... | C | (C,B)... | points[right-1]=B.
6648
6649 // After the swap, p is the index of C (pivot between the two subpaths).
6650 int p = i;
6651 if (i == j and is_positive(points[i]) == a_on_positive)
6652 ++p;
6653 std::swap(points[p], points[right - 2]);
6654
6655 // Path A -> C.
6656 conquer(points, left, p + 1);
6657 // Path C -> B.
6658 conquer(points, p, right);
6659}
6660
6661// Samples k sorted distinct integers from [left, right] uniformly.
6662// Optimized for performance (pool partial Fisher–Yates or complement path for
6663// modest ranges; sparse-map fallback otherwise).
6664// O(k log k); O(right - left) memory when the range is modest.
6665inline std::vector<long long>
6666sample_sorted_distinct_in_range(int k, long long left, long long right) {
6667 long long universe = right - left + 1;
6668 std::vector<long long> res;
6669 res.reserve(k);
6670 if (k == 0)
6671 return res;
6672
6673 constexpr long long pool_threshold = 8'000'000;
6674 constexpr long long pool_always_below = 500'000;
6675
6676 if (universe <= pool_threshold and
6677 (universe <= pool_always_below or k >= universe / 4)) {
6678 size_t u = universe;
6679 size_t ks = k;
6680 std::vector<long long> pool(u);
6681 std::iota(pool.begin(), pool.end(), left);
6682 size_t m = ks <= u / 2 ? ks : u - ks;
6683 for (size_t i = 0; i < m; ++i) {
6684 size_t j = next<size_t>(i, u - 1);
6685 std::swap(pool[i], pool[j]);
6686 }
6687 if (ks <= u / 2) {
6688 res.assign(pool.begin(), pool.begin() + ks);
6689 std::sort(res.begin(), res.end());
6690 } else {
6691 std::vector<char> excluded(u, 0);
6692 for (size_t i = 0; i < m; ++i)
6693 excluded[pool[i] - left] = 1;
6694 for (long long v = left; v <= right; ++v)
6695 if (!excluded[v - left])
6696 res.push_back(v);
6697 }
6698 } else {
6699 std::unordered_map<long long, long long> virtual_list;
6700 virtual_list.reserve(k * 2);
6701 for (long long i = 0; i < k; ++i) {
6702 long long j = next<long long>(i, universe - 1);
6703 long long vi = virtual_list.count(i) ? virtual_list[i] : i;
6704 long long vj = virtual_list.count(j) ? virtual_list[j] : j;
6705 virtual_list[j] = vi;
6706 virtual_list[i] = vj;
6707 res.push_back(virtual_list[i] + left);
6708 }
6709 std::sort(res.begin(), res.end());
6710 }
6711 return res;
6712}
6713
6714// Valtr-style signed edge components along one axis from n sorted distinct
6715// coordinates. The n differences sum to zero.
6716inline std::vector<long long>
6717valtr_edge_components(const std::vector<long long> &sorted_coords) {
6718 int n = sorted_coords.size();
6719 std::vector<long long> left, right;
6720 left.reserve(n / 2);
6721 right.reserve(n / 2);
6722 for (int i = 1; i + 1 < n; ++i) {
6723 if (next(2) == 0)
6724 left.push_back(sorted_coords[i]);
6725 else
6726 right.push_back(sorted_coords[i]);
6727 }
6728 long long lo = sorted_coords.front(), hi = sorted_coords.back();
6729 std::vector<long long> seq;
6730 seq.reserve(n + 1);
6731 seq.push_back(lo);
6732 for (long long v : left)
6733 seq.push_back(v);
6734 seq.push_back(hi);
6735 for (auto it = right.rbegin(); it != right.rend(); ++it)
6736 seq.push_back(*it);
6737 seq.push_back(lo);
6738 std::vector<long long> comps(n);
6739 for (int i = 0; i < n; ++i)
6740 comps[i] = seq[i + 1] - seq[i];
6741 return comps;
6742}
6743
6744// Drops boundary vertices that are collinear with their cyclic neighbors.
6745// O(m), m = |points|.
6746inline std::vector<point<long long>>
6747simplify_strict_boundary(std::vector<point<long long>> points) {
6748 int n = points.size();
6749 if (n < 3)
6750 return points;
6751
6752 std::vector<point<long long>> strict_points;
6753 strict_points.reserve(n);
6754 for (int i = 0; i < n; ++i) {
6755 if (ccw(points[(i + n - 1) % n], points[i], points[(i + 1) % n]) != 0)
6756 strict_points.push_back(points[i]);
6757 }
6758 return strict_points;
6759}
6760
6761// Picks k evenly spaced vertices along a longer cyclic boundary.
6762// O(k).
6763inline std::vector<point<long long>>
6764subsample_boundary(const std::vector<point<long long>> &points, int k) {
6765 int n = points.size();
6766 if (n <= k)
6767 return points;
6768
6769 std::vector<point<long long>> sampled_points;
6770 sampled_points.reserve(k);
6771 for (int i = 0; i < k; ++i)
6772 sampled_points.push_back(points[(static_cast<i128>(i) * n) / k]);
6773 return sampled_points;
6774}
6775
6776// Random translation so the polygon lies in the box.
6777// O(|points|).
6778inline void place_inside_box(std::vector<point<long long>> &points,
6779 long long min_coord, long long max_coord) {
6780 long long width = max_coord - min_coord + 1;
6781
6782 i128 min_x = points[0].x(), max_x = points[0].x();
6783 i128 min_y = points[0].y(), max_y = points[0].y();
6784 for (const point<long long> &p : points) {
6785 min_x = std::min(min_x, static_cast<i128>(p.x()));
6786 max_x = std::max(max_x, static_cast<i128>(p.x()));
6787 min_y = std::min(min_y, static_cast<i128>(p.y()));
6788 max_y = std::max(max_y, static_cast<i128>(p.y()));
6789 }
6790
6791 i128 span_x = max_x - min_x;
6792 i128 span_y = max_y - min_y;
6793 // Random slack keeps the polygon inside the box without filling it.
6794 i128 shift_x =
6795 min_coord - min_x +
6796 next<long long>(0, width - 1 - static_cast<long long>(span_x));
6797 i128 shift_y =
6798 min_coord - min_y +
6799 next<long long>(0, width - 1 - static_cast<long long>(span_y));
6800
6801 for (point<long long> &p : points)
6802 p = point<long long>(p.x() + shift_x, p.y() + shift_y);
6803}
6804
6805// Random cyclic shift.
6806// O(|points|).
6807inline void randomize_cyclic_shift(std::vector<point<long long>> &points) {
6808 int rot = next(points.size());
6809 if (rot > 0)
6810 std::rotate(points.begin(), points.begin() + rot, points.end());
6811}
6812
6813// Valtr walk for m edges; bbox minimum translated to the origin.
6814// O(m log m).
6815inline std::vector<point<long long>>
6816valtr_vertices(int m, const std::vector<long long> &x_comp,
6817 std::vector<long long> y_comp) {
6818 shuffle(y_comp.begin(), y_comp.end());
6819
6820 std::vector<point<long long>> edges(m);
6821 // Upper half-plane (positive y, or y = 0 and x > 0) sorts before lower.
6822 auto upper = [](const point<long long> &p) {
6823 return p.y() > 0 or (p.y() == 0 and p.x() > 0);
6824 };
6825 for (int i = 0; i < m; ++i)
6826 edges[i] = point<long long>(x_comp[i], y_comp[i]);
6827
6828 std::sort(edges.begin(), edges.end(),
6829 [&upper](const point<long long> &a, const point<long long> &b) {
6830 bool au = upper(a), bu = upper(b);
6831 if (au != bu)
6832 return au;
6833 auto cross = a ^ b;
6834 if (cross != 0)
6835 return cross > 0;
6836 return (a * a) < (b * b);
6837 });
6838
6839 // Prefix-sum the sorted edge vectors to obtain vertex coordinates.
6840 i128 cur_x = 0, cur_y = 0;
6841 std::vector<i128> px(m), py(m);
6842 for (int i = 0; i < m; ++i) {
6843 px[i] = cur_x;
6844 py[i] = cur_y;
6845 cur_x += edges[i].x();
6846 cur_y += edges[i].y();
6847 }
6848 tgen::detail::tgen_ensure_against_bug(
6849 cur_x == 0 and cur_y == 0,
6850 "geometry: random_convex_polygon: walk did not close");
6851
6852 i128 min_x = px[0], min_y = py[0];
6853 for (int i = 1; i < m; ++i) {
6854 min_x = std::min(min_x, px[i]);
6855 min_y = std::min(min_y, py[i]);
6856 }
6857
6858 // Shift so the bbox minimum is at the origin.
6859 std::vector<point<long long>> points;
6860 points.reserve(m);
6861 for (int i = 0; i < m; ++i)
6862 points.emplace_back(px[i] - min_x, py[i] - min_y);
6863 return points;
6864}
6865
6866} // namespace detail
6867
6868// Generates n vertices of a convex integer polygon inside a box.
6869// If strict is true, boundary vertices are guaranteed non-collinear when
6870// generation succeeds; retry count depends on n and width.
6871// Always returns points in counterclockwise order.
6872// O(n log n).
6873inline std::vector<point<long long>>
6874random_convex_polygon(int n, long long min_coord, long long max_coord,
6875 bool strict = false) {
6876 tgen_ensure(n >= 3,
6877 "geometry: random_convex_polygon: n must be at least 3");
6878 tgen_ensure(max_coord >= min_coord,
6879 "geometry: random_convex_polygon: min_coord must be at most "
6880 "max_coord");
6881 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord + 1 <=
6882 std::numeric_limits<long long>::max(),
6883 "geometry: random_convex_polygon: coordinate range too large");
6884 long long width = max_coord - min_coord + 1;
6886 width >= n,
6887 "geometry: random_convex_polygon: coordinate range too small for n");
6888
6889 // Valtr walk size: n in weak mode; strict mode uses a larger grid so
6890 // collinear removal still leaves at least n vertices to subsample.
6891 int num_coords = n;
6892 if (strict) {
6893 // Extra grid lines beyond n: at least 100 (small-n headroom), about
6894 // n/1000 for large n, and never more than width - n.
6895 int extra = width <= n ? 0
6896 : std::min<long long>(std::max(100, n / 1000),
6897 width - n);
6898 num_coords = n + extra;
6899 }
6900
6901 // Strict mode retries coordinate sampling when simplification leaves < n
6902 // vertices; weak mode has no failure path, so one attempt always suffices.
6903 const int max_attempts = strict ? 32 : 1;
6904 for (int i = 0; i < max_attempts; ++i) {
6905 // Build a convex lattice polygon on [0, width - 1]^2, then translate.
6906 std::vector<long long> x_sorted =
6907 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6908 std::vector<long long> y_sorted =
6909 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6910 std::vector<long long> x_comp = detail::valtr_edge_components(x_sorted);
6911 std::vector<long long> y_comp = detail::valtr_edge_components(y_sorted);
6912
6913 std::vector<point<long long>> points =
6914 detail::valtr_vertices(num_coords, x_comp, std::move(y_comp));
6915
6916 if (strict) {
6917 std::vector<point<long long>> simplified =
6918 detail::simplify_strict_boundary(std::move(points));
6919 // Tight boxes can leave too few vertices -> resample coordinates.
6920 if (static_cast<int>(simplified.size()) < n)
6921 continue;
6922
6923 points = detail::subsample_boundary(simplified, n);
6924 }
6925
6926 detail::place_inside_box(points, min_coord, max_coord);
6927 detail::randomize_cyclic_shift(points);
6928 return points;
6929 }
6930
6931 // Generation failed.
6932 throw tgen::detail::error(
6933 "geometry: random_convex_polygon: generation failed: coordinate "
6934 "range too small for n");
6935}
6936
6937// Random simple polygon through given distinct points.
6938// Collinear triples are allowed; fails if all points are collinear.
6939// Always returns vertices in counterclockwise order.
6940// O(n log n) expected if points are "random", O(n^2) worst case.
6942 const std::vector<point<long long>> &points) {
6943 int n = points.size();
6944 tgen_ensure(n >= 3,
6945 "geometry: random_simple_polygon_through_points: need at "
6946 "least 3 points");
6948 static_cast<int>(
6949 std::set<point<long long>>(points.begin(), points.end()).size()) ==
6950 n,
6951 "geometry: random_simple_polygon_through_points: points must "
6952 "be distinct");
6953
6954 int idx_a = 0, idx_b = 0;
6955 for (int i = 1; i < n; ++i) {
6956 if (points[i] < points[idx_a])
6957 idx_a = i;
6958 if (points[idx_b] < points[i])
6959 idx_b = i;
6960 }
6961 point<long long> A = points[idx_a], B = points[idx_b];
6962
6963 bool all_collinear = true;
6964 for (int i = 0; i < n; ++i) {
6965 if (i == idx_a or i == idx_b)
6966 continue;
6967 if (detail::ccw(A, B, points[i]) != 0) {
6968 all_collinear = false;
6969 break;
6970 }
6971 }
6972 tgen_ensure(!all_collinear,
6973 "geometry: random_simple_polygon_through_points: all points "
6974 "are collinear; no simple polygon exists");
6975
6976 // Keep points collinear with AB on the chain that has no other points on
6977 // its side, so AB is split through those vertices instead of crossing them
6978 // later.
6979 int negative_count = 0;
6980 for (int i = 0; i < n; ++i) {
6981 if (i == idx_a or i == idx_b)
6982 continue;
6983 if (detail::ccw(A, B, points[i]) < 0)
6984 ++negative_count;
6985 }
6986
6987 std::vector<point<long long>> chain;
6988 chain.push_back(A);
6989 int left_count = 0;
6990 for (int i = 0; i < n; ++i) {
6991 if (i == idx_a or i == idx_b)
6992 continue;
6993 detail::i128 side = detail::ccw(A, B, points[i]);
6994 if (side < 0 or (side == 0 and negative_count == 0)) {
6995 chain.push_back(points[i]);
6996 ++left_count;
6997 }
6998 }
6999 chain.push_back(B);
7000 for (int i = 0; i < n; ++i) {
7001 if (i == idx_a or i == idx_b)
7002 continue;
7003 detail::i128 side = detail::ccw(A, B, points[i]);
7004 if (side > 0 or (side == 0 and negative_count != 0))
7005 chain.push_back(points[i]);
7006 }
7007 chain.push_back(A);
7008
7009 int n1 = 2 + left_count;
7010 // Upper chain: A -> B.
7011 detail::conquer(chain, 0, n1);
7012 // Lower chain: B -> A.
7013 detail::conquer(chain, n1 - 1, chain.size());
7014
7015 // Cyclic vertex order: chain[1..n1) then chain[n1..end) (skip each path's
7016 // start vertex).
7017 std::vector<point<long long>> poly;
7018 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);
7019 poly.insert(poly.end(), chain.begin() + n1, chain.end());
7020 return poly;
7021}
7022
7023namespace detail {
7024
7025// Samples n distinct integer points in [min_coord, max_coord]^2.
7026// O(n log n).
7027inline std::vector<point<long long>>
7028random_distinct_points_in_box(int n, long long min_coord, long long max_coord) {
7029 long long width = max_coord - min_coord;
7030 i128 side_128 = width + 1;
7031 i128 universe = side_128 * side_128;
7032 tgen_ensure(universe <= std::numeric_limits<long long>::max(),
7033 "geometry: random_simple_polygon: coordinate range too large");
7034 long long side = side_128;
7035 tgen_ensure(universe >= n,
7036 "geometry: random_simple_polygon: coordinate range too small "
7037 "for n distinct points");
7038
7039 // Decodes a linear grid key (x * side + y) to a point.
7040 auto decode = [&](long long key) -> point<long long> {
7041 return point<long long>(min_coord + key / side, min_coord + key % side);
7042 };
7043
7044 // Repeats until all generated points are not collinear.
7045 // Runs O(1) expected times.
7046 while (true) {
7047 std::vector<long long> keys =
7048 distinct_range<long long>(0, universe - 1).gen_list(n).to_std();
7049
7050 std::vector<point<long long>> points;
7051 points.reserve(n);
7052 for (long long key : keys)
7053 points.push_back(decode(key));
7054
7055 // Checks if the points are not all collinear.
7056 for (int i = 2; i < n; ++i) {
7057 if (ccw(points[0], points[1], points[i]) != 0)
7058 return points;
7059 }
7060 }
7061}
7062
7063// Axis-aligned edge data for a CCW polygon (interior on the left).
7064// O(1).
7065struct ortho_poly_edge {
7066 long long len;
7067 bool horiz;
7068 long long fixed;
7069 long long lo, hi;
7070 int out_x, out_y;
7071};
7072
7073// True if a, b, c lie on one horizontal or vertical line.
7074// O(1).
7075inline bool ortho_axis_collinear(const point<long long> &a,
7076 const point<long long> &b,
7077 const point<long long> &c) {
7078 return (a.x() == b.x() and b.x() == c.x()) or
7079 (a.y() == b.y() and b.y() == c.y());
7080}
7081
7082// Edge i of poly: orientation, span, exterior normal.
7083// O(1).
7084inline ortho_poly_edge
7085ortho_analyze_edge(const std::vector<point<long long>> &poly, int i) {
7086 int m = poly.size();
7087 point<long long> a = poly[i], b = poly[(i + 1) % m];
7088 ortho_poly_edge e{};
7089 if (a.y() == b.y()) {
7090 e.horiz = true;
7091 e.fixed = a.y();
7092 e.lo = std::min(a.x(), b.x());
7093 e.hi = std::max(a.x(), b.x());
7094 e.out_x = 0;
7095 e.out_y = a.x() < b.x() ? -1 : 1;
7096 } else {
7097 e.fixed = a.x();
7098 e.lo = std::min(a.y(), b.y());
7099 e.hi = std::max(a.y(), b.y());
7100 e.out_x = a.y() < b.y() ? 1 : -1;
7101 }
7102 e.len = e.hi - e.lo;
7103 return e;
7104}
7105
7106// True if open axis-aligned segments (a, b) and (c, d) properly cross or
7107// overlap (excluding shared endpoints).
7108// O(1).
7109inline bool ortho_open_seg_cross(const point<long long> &a,
7110 const point<long long> &b,
7111 const point<long long> &c,
7112 const point<long long> &d) {
7113 if (a.y() == b.y() and c.y() == d.y()) {
7114 if (a.y() != c.y())
7115 return false;
7116 long long lo1 = std::min(a.x(), b.x()), hi1 = std::max(a.x(), b.x());
7117 long long lo2 = std::min(c.x(), d.x()), hi2 = std::max(c.x(), d.x());
7118 return lo1 < hi2 and lo2 < hi1;
7119 }
7120 if (a.x() == b.x() and c.x() == d.x()) {
7121 if (a.x() != c.x())
7122 return false;
7123 long long lo1 = std::min(a.y(), b.y()), hi1 = std::max(a.y(), b.y());
7124 long long lo2 = std::min(c.y(), d.y()), hi2 = std::max(c.y(), d.y());
7125 return lo1 < hi2 and lo2 < hi1;
7126 }
7127 if (a.y() == b.y() and c.x() == d.x()) {
7128 long long hx = a.y(), vx = c.x();
7129 long long hlo = std::min(a.x(), b.x()), hhi = std::max(a.x(), b.x());
7130 long long vlo = std::min(c.y(), d.y()), vhi = std::max(c.y(), d.y());
7131 return hlo < vx and vx < hhi and vlo < hx and hx < vhi;
7132 }
7133 if (a.x() == b.x() and c.y() == d.y()) {
7134 long long vx = a.x(), hy = c.y();
7135 long long vlo = std::min(a.y(), b.y()), vhi = std::max(a.y(), b.y());
7136 long long hlo = std::min(c.x(), d.x()), hhi = std::max(c.x(), d.x());
7137 return vlo < hy and hy < vhi and hlo < vx and vx < hhi;
7138 }
7139 return false;
7140}
7141
7142// Integral ray-crossing point-in-polygon.
7143// O(|poly|).
7144inline bool ortho_point_inside(const std::vector<point<long long>> &poly,
7145 point<long long> p) {
7146 int m = poly.size();
7147 bool inside = false;
7148 for (int i = 0, j = m - 1; i < m; j = i++) {
7149 point<long long> a = poly[i], b = poly[j];
7150 if ((a.y() > p.y()) != (b.y() > p.y())) {
7151 i128 x_cross = i128(b.x() - a.x()) * (p.y() - a.y()) -
7152 i128(p.x() - a.x()) * (b.y() - a.y());
7153 if ((a.y() < b.y()) ? x_cross > 0 : x_cross < 0)
7154 inside = !inside;
7155 }
7156 }
7157 return inside;
7158}
7159
7160// True if p lies strictly in the open segment (a, b).
7161// O(1).
7162inline bool ortho_point_strictly_interior(point<long long> p,
7163 point<long long> a,
7164 point<long long> b) {
7165 if (a.y() == b.y()) {
7166 if (p.y() != a.y())
7167 return false;
7168 long long lo = std::min(a.x(), b.x()), hi = std::max(a.x(), b.x());
7169 return lo < p.x() and p.x() < hi;
7170 }
7171 if (a.x() == b.x()) {
7172 if (p.x() != a.x())
7173 return false;
7174 long long lo = std::min(a.y(), b.y()), hi = std::max(a.y(), b.y());
7175 return lo < p.y() and p.y() < hi;
7176 }
7177 return false;
7178}
7179
7180// True if p lies on the closed segment [a, b].
7181// O(1).
7182inline bool ortho_point_on_segment(point<long long> p, point<long long> a,
7183 point<long long> b) {
7184 return p == a or p == b or ortho_point_strictly_interior(p, a, b);
7185}
7186
7187// True if splicing add between A and B on edge_i is valid: no vertex of add
7188// coincides with poly, no boundary self-contact (forward or reverse
7189// T-junctions, collinear overlaps), new segments do not cross other boundary
7190// edges, and inward notches keep all of add inside poly.
7191// O(|poly|), assuming |add| is O(1).
7192inline bool ortho_bump_valid(const std::vector<point<long long>> &poly,
7193 point<long long> A, point<long long> B,
7194 const std::vector<point<long long>> &add,
7195 int edge_i, bool inward) {
7196 int m = poly.size();
7197
7198 for (point<long long> v : add)
7199 for (point<long long> q : poly)
7200 if (v == q)
7201 return false;
7202
7203 // Forward T-junction: new vertex on a non-incident edge interior, or on
7204 // edge_i but outside the replaced subsegment [A, B].
7205 for (point<long long> v : add) {
7206 for (int j = 0; j < m; ++j) {
7207 point<long long> c = poly[j], d = poly[(j + 1) % m];
7208 if (j == edge_i) {
7209 if (ortho_point_on_segment(v, c, d) and
7210 !ortho_point_on_segment(v, A, B))
7211 return false;
7212 } else if (ortho_point_strictly_interior(v, c, d)) {
7213 return false;
7214 }
7215 }
7216 }
7217
7218 auto seg_ok = [&](point<long long> s0, point<long long> s1) {
7219 for (int j = 0; j < m; ++j) {
7220 if (j == edge_i)
7221 continue;
7222 point<long long> c = poly[j], d = poly[(j + 1) % m];
7223 if (ortho_open_seg_cross(s0, s1, c, d))
7224 return false;
7225 }
7226 for (int k = 0; k < m; ++k) {
7227 point<long long> q = poly[k];
7228 if (q == s0 or q == s1 or q == A or q == B)
7229 continue;
7230 if (ortho_point_strictly_interior(q, s0, s1))
7231 return false;
7232 }
7233 return true;
7234 };
7235
7236 point<long long> prev = A;
7237 for (point<long long> v : add) {
7238 if (!seg_ok(prev, v))
7239 return false;
7240 prev = v;
7241 }
7242 if (!seg_ok(prev, B))
7243 return false;
7244
7245 if (inward) {
7246 for (point<long long> v : add)
7247 if (!ortho_point_inside(poly, v))
7248 return false;
7249 }
7250
7251 return true;
7252}
7253
7254// Splices a rectangular tab or notch on edge edge_i over [lo, hi], extending
7255// depth units perpendicular to the edge.
7256// O(|poly|).
7257inline bool ortho_bump_edge(std::vector<point<long long>> &poly, int edge_i,
7258 const ortho_poly_edge &e, long long lo,
7259 long long hi, long long depth, bool inward) {
7260 int m = poly.size();
7261 point<long long> A = poly[edge_i], B = poly[(edge_i + 1) % m];
7262
7263 int step_x = inward ? -e.out_x : e.out_x;
7264 int step_y = inward ? -e.out_y : e.out_y;
7265
7266 std::vector<point<long long>> add;
7267 if (e.horiz) {
7268 long long y = e.fixed, y2 = y + step_y * depth;
7269 if (A.x() < B.x()) {
7270 if (lo > A.x())
7271 add.emplace_back(lo, y);
7272 add.emplace_back(lo, y2);
7273 add.emplace_back(hi, y2);
7274 if (hi < B.x())
7275 add.emplace_back(hi, y);
7276 } else {
7277 if (hi < A.x())
7278 add.emplace_back(hi, y);
7279 add.emplace_back(hi, y2);
7280 add.emplace_back(lo, y2);
7281 if (lo > B.x())
7282 add.emplace_back(lo, y);
7283 }
7284 } else {
7285 long long x = e.fixed, x2 = x + step_x * depth;
7286 if (A.y() < B.y()) {
7287 if (lo > A.y())
7288 add.emplace_back(x, lo);
7289 add.emplace_back(x2, lo);
7290 add.emplace_back(x2, hi);
7291 if (hi < B.y())
7292 add.emplace_back(x, hi);
7293 } else {
7294 if (hi < A.y())
7295 add.emplace_back(x, hi);
7296 add.emplace_back(x2, hi);
7297 add.emplace_back(x2, lo);
7298 if (lo > B.y())
7299 add.emplace_back(x, lo);
7300 }
7301 }
7302 if (!ortho_bump_valid(poly, A, B, add, edge_i, inward))
7303 return false;
7304
7305 poly.insert(poly.begin() + edge_i + 1, add.begin(), add.end());
7306 return true;
7307}
7308
7309// Picks edge i with probability proportional to
7310// e.len * (4 + min(global_timestamp - last_used[i], 8)).
7311// O(|poly|).
7312inline int ortho_pick_poly_edge(const std::vector<point<long long>> &poly,
7313 std::vector<int> &last_used, int &time_stamp) {
7314 int m = poly.size();
7315 if (last_used.size() != static_cast<size_t>(m)) {
7316 last_used.assign(m, 0);
7317 time_stamp = 0;
7318 }
7319 std::vector<long long> weights(m);
7320 long long total = 0;
7321 for (int i = 0; i < m; ++i) {
7322 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7323 weights[i] = e.len * (4 + std::min(time_stamp - last_used[i], 8));
7324 total += weights[i];
7325 }
7326 long long pick = next<long long>(0, total - 1);
7327 for (int i = 0; i < m; ++i) {
7328 pick -= weights[i];
7329 if (pick < 0) {
7330 last_used[i] = ++time_stamp;
7331 return i;
7332 }
7333 }
7334 last_used[m - 1] = ++time_stamp;
7335 return m - 1;
7336}
7337
7338// One random inflate/cut attempt.
7339// O(|poly|).
7340inline bool ortho_try_bump(std::vector<point<long long>> &poly, int n,
7341 std::vector<int> &last_used, int &time_stamp,
7342 bool outward_only = false) {
7343 if (poly.size() < 3)
7344 return false;
7345
7346 int ei = ortho_pick_poly_edge(poly, last_used, time_stamp);
7347 ortho_poly_edge e = ortho_analyze_edge(poly, ei);
7348
7349 // Edge subdivision can leave length-1 segments; a tab needs span >= 2.
7350 if (e.len < 2)
7351 return false;
7352
7353 // Random subinterval [lo, lo + span] on the edge, with 2 <= span <= e.len.
7354 long long span = next<long long>(2, e.len);
7355 long long lo = next<long long>(e.lo, e.hi - span);
7356
7357 // max_depth: cap on perpendicular tab/notch height (~sqrt(n), in [2, 12]).
7358 // depth: actual height; shallow usually, up to max_depth 10% of the time.
7359 long long max_depth =
7360 std::clamp<long long>(std::sqrt(n) / 2 + 2, 2LL, 12LL);
7361 long long depth =
7362 next(10) == 0 ? next<long long>(std::max(2LL, max_depth / 2), max_depth)
7363 : next<long long>(1, std::max(2LL, max_depth / 3));
7364
7365 bool inward = !outward_only and next(4) == 0;
7366 return ortho_bump_edge(poly, ei, e, lo, lo + span, depth, inward);
7367}
7368
7369// Drops axis-aligned collinear vertices.
7370// O(n).
7371inline std::vector<point<long long>>
7372ortho_simplify_collinear(std::vector<point<long long>> poly) {
7373 int n = poly.size();
7374 if (n < 3)
7375 return poly;
7376 std::vector<point<long long>> out;
7377 out.reserve(n);
7378 for (int i = 0; i < n; ++i) {
7379 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7380 poly[(i + 1) % n]))
7381 out.push_back(poly[i]);
7382 }
7383 return out.size() >= 3 ? out : poly;
7384}
7385
7386// Removes one collinear vertex.
7387// O(n).
7388inline bool ortho_remove_one_collinear(std::vector<point<long long>> &poly) {
7389 int n = poly.size();
7390 if (n < 4)
7391 return false;
7392 for (int i = 0; i < n; ++i) {
7393 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7394 poly[(i + 1) % n]))
7395 continue;
7396 poly.erase(poly.begin() + i);
7397 return true;
7398 }
7399 return false;
7400}
7401
7402// Inserts collinear vertices on straight edges until size reaches `target` (or
7403// no edge has spare integer points). Preserves boundary order.
7404// O(target).
7405inline void ortho_fill_collinear(std::vector<point<long long>> &poly,
7406 int target) {
7407 int need = target - poly.size();
7408 if (need <= 0)
7409 return;
7410
7411 std::vector<point<long long>> out;
7412 int m = poly.size();
7413 out.reserve(poly.size() + need);
7414
7415 for (int i = 0; i < m; ++i) {
7416 point<long long> a = poly[i], b = poly[(i + 1) % m];
7417 out.push_back(a);
7418 if (need <= 0)
7419 continue;
7420
7421 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7422 long long cap = e.len - 1;
7423 if (cap <= 0)
7424 continue;
7425
7426 // Adds `take` collinear vertices to the boundary.
7427 long long take = std::min<long long>(need, cap);
7428 bool forward = e.horiz ? a.x() < b.x() : a.y() < b.y();
7429 for (long long k = 0; k < take; ++k) {
7430 long long off = (k + 1) * (cap + 1) / (take + 1);
7431 long long coord = forward ? e.lo + off : e.hi - off;
7432 if (e.horiz)
7433 out.push_back({coord, e.fixed});
7434 else
7435 out.push_back({e.fixed, coord});
7436 }
7437 need -= take;
7438 }
7439 poly.swap(out);
7440}
7441
7442// Inserts outward depth-1 corrugation tabs on straight edges until size reaches
7443// `target` (or no edge has room for another tab). Preserves boundary order.
7444// Assumes the scale-up step left every edge on a grid with spacing >= 4.
7445// Each tab perturbs a coordinate by 1 and keeps a >= 2 margin from both
7446// corners, so tabs can only meet tabs on the same or a directly facing edge.
7447// The result is therefore simple and free of collinear triples by construction.
7448// O(target).
7449inline void ortho_fill_corrugation(std::vector<point<long long>> &poly,
7450 size_t target) {
7451 size_t n_sz = poly.size();
7452 if (n_sz >= target)
7453 return;
7454
7455 size_t extra_left = target - n_sz;
7456
7457 std::vector<point<long long>> out;
7458 out.reserve(target);
7459 int n = poly.size();
7460
7461 for (int i = 0; i < n; ++i) {
7462 point<long long> a = poly[i], b = poly[(i + 1) % n];
7463 out.push_back(a);
7464
7465 if (extra_left < 4)
7466 continue;
7467
7468 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7469 if (e.len < 5)
7470 continue;
7471
7472 long long dir = (e.horiz ? a.x() < b.x() : a.y() < b.y()) ? 1 : -1;
7473 long long start = e.horiz ? a.x() : a.y();
7474 long long end = e.horiz ? b.x() : b.y();
7475
7476 for (long long pos = start + 2 * dir;
7477 extra_left >= 4 and (pos - end) * dir <= -3; pos += 2 * dir) {
7478 if (e.horiz) {
7479 long long y2 = e.fixed + e.out_y;
7480 out.push_back({pos, e.fixed});
7481 out.push_back({pos, y2});
7482 out.push_back({pos + dir, y2});
7483 out.push_back({pos + dir, e.fixed});
7484 } else {
7485 long long x2 = e.fixed + e.out_x;
7486 out.push_back({e.fixed, pos});
7487 out.push_back({x2, pos});
7488 out.push_back({x2, pos + dir});
7489 out.push_back({e.fixed, pos + dir});
7490 }
7491 extra_left -= 4;
7492 }
7493 }
7494
7495 poly.swap(out);
7496}
7497
7498// CCW square seed plus boundary inflate/cut to about n vertices.
7499// O(n^2) for n <= 1000; O(n) otherwise.
7500inline std::vector<point<long long>> build_orthogonal_polygon(int n,
7501 bool strict) {
7502 bool scale_up = n > 1000;
7503
7504 long long side = std::max<long long>(3, std::sqrt(n));
7505 if (scale_up)
7506 side = std::clamp(static_cast<long long>(2 * std::sqrt(std::sqrt(n))),
7507 8LL, 64LL);
7508 std::vector<point<long long>> poly = {
7509 {0, 0}, {side, 0}, {side, side}, {0, side}};
7510
7511 int target_ops = scale_up ? std::max(1, static_cast<int>(4 * side - 4) / 2)
7512 : std::max(1, (n - 4) / 2);
7513
7514 if (scale_up)
7515 target_ops = std::min(
7516 target_ops,
7517 400 + static_cast<int>(4 * std::sqrt(static_cast<double>(side))));
7518
7519 int failure_limit = std::min(target_ops * 8, 2000);
7520
7521 std::vector<int> last_used;
7522 int time_stamp = 0, consecutive_failures = 0;
7523 for (int ops = 0; ops < target_ops;) {
7524 if (!scale_up and poly.size() + 2 > static_cast<size_t>(n))
7525 break;
7526
7527 if (ortho_try_bump(poly, n, last_used, time_stamp, scale_up)) {
7528 ++ops;
7529 consecutive_failures = 0;
7530 } else if (++consecutive_failures >= failure_limit) {
7531 break;
7532 }
7533 }
7534 if (strict)
7535 poly = ortho_simplify_collinear(std::move(poly));
7536
7537 if (scale_up) {
7538 while (poly.size() > static_cast<size_t>(n) and
7539 ortho_remove_one_collinear(poly))
7540 ;
7541 long long upscale = std::max(4LL, ((n + 3) / 4 + side - 1) / side);
7542 for (point<long long> &p : poly)
7543 p = {p.x() * upscale, p.y() * upscale};
7544 if (strict)
7545 ortho_fill_corrugation(poly, n);
7546 else
7547 ortho_fill_collinear(poly, n);
7548 } else if (!strict)
7549 ortho_fill_collinear(poly, n);
7550
7551 return poly;
7552}
7553
7554} // namespace detail
7555
7556// Random simple polygon.
7557// If strict, vertex set has no three collinear points
7558// (random_points_general_position); otherwise samples distinct grid points
7559// (collinear triples allowed), so it might be the case that (polygon[i],
7560// polygon[i+1], and polygon[i+2]) are collinear. Polygonizes via
7561// random_simple_polygon_through_points. Always counterclockwise.
7562// O(n log n) expected.
7563inline std::vector<point<long long>>
7564random_simple_polygon(int n, long long min_coord, long long max_coord,
7565 bool strict = false) {
7566 tgen_ensure(n >= 3,
7567 "geometry: random_simple_polygon: n must be at least 3");
7568 tgen_ensure(max_coord >= min_coord,
7569 "geometry: random_simple_polygon: min_coord must be at most "
7570 "max_coord");
7571 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord <=
7572 std::numeric_limits<long long>::max(),
7573 "geometry: random_simple_polygon: coordinate range too large");
7574
7575 std::vector<point<long long>> points =
7576 strict ? random_points_general_position(n, min_coord, max_coord)
7577 : detail::random_distinct_points_in_box(n, min_coord, max_coord);
7578 return random_simple_polygon_through_points(points);
7579}
7580
7581// Random orthogonal simple polygon, CCW. Each local bump/scale/fill step
7582// preserves full simplicity, so the result is valid by construction.
7583// Exactly n vertices when !strict; at most n when strict (near n for n > 1000).
7584// O(n^2) for n <= 1000; O(n) otherwise.
7585inline std::vector<point<long long>>
7586random_orthogonal_polygon(int n, long long min_coord, long long max_coord,
7587 bool strict = false) {
7588 tgen_ensure(n >= 4,
7589 "geometry: random_orthogonal_polygon: n must be at least 4");
7590 tgen_ensure(max_coord >= min_coord,
7591 "geometry: random_orthogonal_polygon: min_coord must be at "
7592 "most max_coord");
7593 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7594 std::numeric_limits<long long>::max(),
7595 "geometry: random_orthogonal_polygon: coordinate range too "
7596 "large");
7597 long long width = max_coord - min_coord + 1;
7598 tgen_ensure(width >= 4,
7599 "geometry: random_orthogonal_polygon: coordinate range too "
7600 "small");
7601
7602 long long min_side = std::max<long long>(3, std::sqrt(n));
7603 if (n > 1000)
7604 min_side = std::max<long long>(min_side, (n + 3) / 4);
7605 tgen_ensure(min_side < width,
7606 "geometry: random_orthogonal_polygon: coordinate range too "
7607 "small");
7608
7609 for (int attempt = 0; attempt < 8; ++attempt) {
7610 std::vector<point<long long>> poly =
7611 detail::build_orthogonal_polygon(n, strict);
7612
7613 if (!strict and poly.size() != static_cast<size_t>(n))
7614 continue;
7615
7616 detail::i128 min_x = poly[0].x(), max_x = poly[0].x();
7617 detail::i128 min_y = poly[0].y(), max_y = poly[0].y();
7618 for (point<long long> p : poly) {
7619 min_x = std::min(min_x, detail::i128(p.x()));
7620 max_x = std::max(max_x, detail::i128(p.x()));
7621 min_y = std::min(min_y, detail::i128(p.y()));
7622 max_y = std::max(max_y, detail::i128(p.y()));
7623 }
7624 if (max_x - min_x >= width or max_y - min_y >= width)
7625 continue;
7626
7627 detail::place_inside_box(poly, min_coord, max_coord);
7628 detail::randomize_cyclic_shift(poly);
7629 return poly;
7630 }
7631
7632 throw tgen::detail::error(
7633 "geometry: random_orthogonal_polygon: generation failed");
7634}
7635
7636} // namespace geometry
7637
7638/************
7639 * *
7640 * HACK *
7641 * *
7642 ************/
7643
7644namespace hack {
7645
7646namespace detail {
7647
7648using namespace tgen::detail;
7649
7650// Computes polynomial hash of a string.
7651// O(|s|).
7652inline int hash_string(const std::string &s, int base, int mod) {
7653 long long h = 0;
7654 for (char c : s)
7655 h = (h * base + c - 'a' + 1) % mod;
7656 return h;
7657}
7658
7659// Estimates the length of the string to very likely have a collision.
7660inline int estimate_length(int alphabet_size, int mod) {
7661 // Magic constants.
7662 double base_len = 2.5 * std::log(std::sqrt(mod));
7663 double scale = std::log(alphabet_size) / std::log(2.0);
7664 double adjusted = base_len / std::max(1.0, scale * 0.7);
7665
7666 return static_cast<int>(std::ceil(adjusted));
7667}
7668
7669// Collides two strings to have the same polynomial hash.
7670// O(sqrt(mod) log(mod)) with high probability.
7671inline std::pair<std::string, std::string>
7672birthday_attack(const std::vector<std::string> &alphabet, int base, int mod) {
7673 tgen_ensure(0 < base and base < mod,
7674 "birthday_attack: base must be in (0, mod)");
7675 std::map<uint64_t, std::vector<int>> seen;
7676 int length = estimate_length(alphabet.size(), mod);
7677
7678 while (true) {
7679 std::vector<int> seq(length);
7680
7681 std::string s;
7682
7683 for (int i = 0; i < length; ++i) {
7684 seq[i] = next<int>(0, alphabet.size() - 1);
7685 s += alphabet[seq[i]];
7686 }
7687
7688 int h = hash_string(s, base, mod);
7689
7690 auto it = seen.find(h);
7691 if (it != seen.end() and it->second != seq) {
7692 std::string a, b;
7693
7694 for (int x : it->second)
7695 a += alphabet[x];
7696 for (int x : seq)
7697 b += alphabet[x];
7698
7699 if (a != b)
7700 return {a, b};
7701 }
7702
7703 seen[h] = seq;
7704 }
7705}
7706
7707// Tried to find correct multipliers for unordered_map/set to force
7708// collisions. O(1).
7709inline std::set<long long> std_hash_multipliers() {
7710 std::set<long long> multipliers = {85229};
7711
7712 // Codeforces GCC GNU G++17 7.3.0 case.
7713 bool codeforces_gcc_case = true;
7714 if (cpp.version_ != 0 and cpp.version_ != 17)
7715 codeforces_gcc_case = false;
7716 if (compiler.kind_ != compiler_kind::unknown and
7717 compiler.kind_ != compiler_kind::gcc)
7718 codeforces_gcc_case = false;
7719 if (compiler.major_ > 7)
7720 codeforces_gcc_case = false;
7721
7722 if (codeforces_gcc_case)
7723 multipliers.insert(107897);
7724
7725 return multipliers;
7726}
7727
7728} // namespace detail
7729
7730// Fetches prefix of length n of the string "abacabadabacabae...".
7731// O(n).
7732inline std::string abacaba(int n) {
7733 tgen_ensure(n > 0, "str: size must be positive");
7734 std::string str = "a";
7735 char c = 'a';
7736 while (static_cast<int>(str.size()) < n) {
7737 int prev_size = str.size();
7738 str += ++c;
7739 for (int j = 0; j < prev_size and static_cast<int>(str.size()) < n; ++j)
7740 str += str[j];
7741 }
7742 return str;
7743}
7744
7745// Two strings that have same polynomial hash for any base, for
7746// mod = power of 2 up to 2^64.
7747// Thue–Morse.
7748// O(1).
7749inline std::pair<std::string, std::string> unsigned_polynomial_hash() {
7750 std::string a, b;
7751 int size = 1 << 10;
7752 for (int i = 0; i < size; ++i) {
7753 a += 'a' + math::detail::popcount(i) % 2;
7754 b += 'a' + ('b' - a[i]);
7755 }
7756 return {a, b};
7757}
7758
7759// Collides two strings to have the same polynomial hash.
7760// O(sqrt(mod) log(mod)) with high probability.
7761// 0 < base < mod.
7762inline std::pair<std::string, std::string> polynomial_hash(int alphabet_size,
7763 int base, int mod) {
7764 tgen_ensure(alphabet_size > 1,
7765 "hack: polynomial_hash: alphabet size must be greater "
7766 "than 1");
7767 tgen_ensure(0 < base and base < mod,
7768 "hack: polynomial_hash: base must be in (0, mod)");
7769
7770 std::vector<std::string> alphabet(alphabet_size);
7771 for (int i = 0; i < alphabet_size; ++i)
7772 alphabet[i] = std::string(1, 'a' + i);
7773 std::iota(alphabet.begin(), alphabet.end(), 'a');
7774 return detail::birthday_attack(alphabet, base, mod);
7775}
7776
7777// Collides two strings to have the same polynomial hash for multiple bases
7778// and mods (up to 2 pairs).
7779// O(sqrt(mod) log^2 (mod)) with high probability,
7780// with mod = max(mod_1, mod_2).
7781inline std::pair<std::string, std::string>
7782polynomial_hash(int alphabet_size, std::vector<int> bases,
7783 std::vector<int> mods) {
7784 tgen_ensure(bases.size() == mods.size(),
7785 "hack: polynomial_hash: bases and mods must have the same "
7786 "size");
7787 tgen_ensure(bases.size() > 0,
7788 "hack: polynomial_hash: must have at least one (base, mod) "
7789 "pair");
7790 tgen_ensure(bases.size() <= 2,
7791 "hack: polynomial_hash: multi-hash hack only supported "
7792 "for up to 2 (base, mod) pairs");
7793
7794 std::vector<std::string> alphabet(alphabet_size);
7795 for (int i = 0; i < alphabet_size; ++i)
7796 alphabet[i] = std::string(1, 'a' + i);
7797 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);
7798 if (bases.size() == 1)
7799 return {S1, T1};
7800 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);
7801}
7802
7803// Returns a list of integers for unordered_map/set to force collisions.
7804// O(size).
7805inline std::vector<long long> std_unordered(int size) {
7806 tgen_ensure(size > 0, "hack: std_unordered: size must be positive");
7807 std::set<long long> multipliers = detail::std_hash_multipliers();
7808 long long mult = 1;
7809 std::set<long long>::iterator it = multipliers.begin();
7810
7811 std::vector<long long> list;
7812 while (static_cast<int>(list.size()) < size) {
7813 list.push_back(mult * (*it));
7814 ++it;
7815 if (it == multipliers.end()) {
7816 it = multipliers.begin();
7817 ++mult;
7818 }
7819 }
7820 return list;
7821}
7822
7823// Returns queries that force \Theta(q sqrt n) asymptotic
7824// for Mo algorithm for offline range queries.
7825// Forces \Theta(q sqrt n) pointer moves for any ordering.
7826// O(n log n + q).
7827inline std::vector<std::pair<int, int>> mo_worst_case(int n, int q) {
7828 std::set<std::pair<int, int>> queries;
7829
7830 // Adversarial case.
7831 int sq = std::sqrt(n);
7832 for (int i = 0; i < sq; ++i) {
7833 for (int j = i; j < sq; ++j) {
7834 if (i * sq < n and j * sq < n)
7835 queries.emplace(i * sq, j * sq);
7836 }
7837 }
7838
7839 // Push extra queries.
7840 for (int i = 0; i < n; ++i)
7841 if (queries.size() < size_t(q)) {
7842 queries.emplace(0, i);
7843 queries.emplace(i, i);
7844 queries.emplace(i, n - 1);
7845 }
7846
7847 std::vector<std::pair<int, int>> pool(queries.begin(), queries.end());
7848 while (pool.size() < size_t(q)) {
7849 int l = next(0, n - 1);
7850 pool.emplace_back(l, next(l, n - 1));
7851 }
7852
7853 return choose(shuffled(pool), q);
7854}
7855
7856// Returns list of strings that have a high cost to insert in a std::set.
7857// Forces cost \Theta(size log(size)).
7858// Generates: {b, ab, aab, aaab, ...}.
7859// O(size log(size)).
7861 std::vector<std::string> list;
7862 int k = 0, left = size;
7863 while (left > 0) {
7864 int cur_size = std::min(left, k + 1);
7865 left -= cur_size;
7866
7867 char right_char = cur_size == k + 1 ? 'b' : 'c';
7868 list.push_back(std::string(cur_size - 1, 'a') + right_char);
7869
7870 ++k;
7871 }
7872 return tgen::shuffled(list);
7873}
7874
7875// Graph for Dijkstra implementations that relax with <= instead of <.
7876// Unit-weight layered graph: 0 -> {1,2}, then disjoint
7877// 2x2 gadgets (i,i+1) -> {i+2,i+3} for i = 1,3,5,... Many vertices share the
7878// same dist from 0; with `d + w <= dist[j]` each pop re-relaxes the whole
7879// frontier below it. m = 2(n - 2) edges.
7880// O(n).
7883 n >= 3,
7884 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");
7885
7886 egraph<int>::value g(n, {}, true);
7887 g.edge_weighted();
7888 g.add_edge(0, 1, 1);
7889 g.add_edge(0, 2, 1);
7890 for (int i = 1; i + 2 < n; i += 2) {
7891 g.add_edge(i, i + 2, 1);
7892 if (i + 3 < n)
7893 g.add_edge(i, i + 3, 1);
7894
7895 g.add_edge(i + 1, i + 2, 1);
7896 if (i + 3 < n)
7897 g.add_edge(i + 1, i + 3, 1);
7898 }
7899
7900 return g.shuffle_except({0});
7901}
7902
7903// Graph for Dijkstra implementations that do not skip stale heap entries
7904// (`if (d > dist[i]) continue`).
7905// Hub mid = n/2: star 0 -> 1..mid-1 (weights 1..mid-1), funnel i -> mid
7906// (weights 1,3,5,...), then mid -> mid+1.. (weight 1).
7907// Without a stale-heap check, mid and its in-neighbors are re-popped and
7908// re-relax.
7909// m = n + mid - 3 edges, mid = floor(n/2).
7910// O(n).
7912 tgen_ensure(n >= 4,
7913 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");
7914
7915 int mid = n / 2;
7916 egraph<int>::value g(n, {}, true);
7917 g.edge_weighted();
7918 for (int i = 1; i < mid; ++i)
7919 g.add_edge(0, i, i);
7920 for (int i = 1; i < mid; ++i)
7921 g.add_edge(i, mid, 2 * (mid - i) - 1);
7922 for (int i = mid + 1; i < n; ++i)
7923 g.add_edge(mid, i, 1);
7924
7925 return g.shuffle_except({0});
7926}
7927
7928// Worst-case for FIFO-SPFA.
7929// Forces Omega(n^2) from vertex 0 (Theta(n*m), m = 2n - 3).
7930// Upper chain ai -> a(i+1) weight 1; lower chain bi -> b(i+1) weight 0;
7931// vertical ai -> bi weight 0; cross bi -> a(i+1) weight 1. Upper chain sets
7932// loose dist first; cross edges from settled bi then improve a(i+1).
7933// m = 2n - 3.
7934// O(n).
7935inline egraph<int>::value spfa(int n) {
7936 tgen_ensure(n >= 2, "hack: spfa: n must be at least 2");
7937 tgen_ensure(n % 2 == 0, "hack: spfa: n must be even");
7938
7939 egraph<int>::value g(n, {}, true);
7940 g.edge_weighted();
7941
7942 const int k = n / 2;
7943 for (int i = 0; i + 1 < k; ++i)
7944 g.add_edge(i, i + 1, 1);
7945 for (int i = 0; i + 1 < k; ++i)
7946 g.add_edge(k + i, k + i + 1, 0);
7947 for (int i = 0; i < k; ++i)
7948 g.add_edge(i, k + i, 0);
7949 for (int i = 0; i + 1 < k; ++i)
7950 g.add_edge(k + i, i + 1, 1);
7951
7952 return g.shuffle_except({0});
7953}
7954
7955// Zadeh (1972) anti-shortest-paths flow network for Edmonds-Karp and Dinitz.
7956// Source is vertex 0; sink is vertex 4l + 2k + 1.
7957// n = 4l + 2k + 2, m = 6l + 4k + k^2 - 4.
7958// O(l + k^2).
7959inline egraph<int>::value dinitz_worst_case(int k, int l) {
7960 tgen_ensure(k >= 1, "hack: dinitz_worst_case: k must be at least 1");
7961 tgen_ensure(l >= 1, "hack: dinitz_worst_case: l must be at least 1");
7962
7963 const int p1 = 2 * l - 1;
7964 const int p2 = 2 * l;
7965 const int q1 = 2 * l + 1;
7966 const int q2 = 2 * l + 2;
7967 const int n = 4 * l + 2 * k + 2;
7968
7969 const int flow_cap = k * k * l;
7970 const int layer_cap = k * k;
7971
7972 auto a = [&](int i) { return 2 * l + 3 + 2 * i; };
7973 auto b = [&](int i) { return 2 * l + 4 + 2 * i; };
7974 auto t = [&](int i) { return 4 * l + 2 * k + 1 - i; };
7975
7976 egraph<int>::value g(n, {}, true);
7977 g.edge_weighted();
7978
7979 for (int i = 0; i + 1 < 2 * l - 1; ++i)
7980 g.add_edge(i, i + 1, flow_cap);
7981 for (int i = 0; i + 1 < 2 * l - 1; ++i)
7982 g.add_edge(t(i + 1), t(i), flow_cap);
7983
7984 for (int i = 0; i < 2 * l - 1; i += 2) {
7985 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);
7986 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);
7987 }
7988
7989 for (int i = 0; i < k; ++i) {
7990 g.add_edge(p1, a(i), flow_cap);
7991 g.add_edge(p2, b(i), flow_cap);
7992 g.add_edge(a(i), q2, flow_cap);
7993 g.add_edge(b(i), q1, flow_cap);
7994 }
7995
7996 for (int i = 0; i < k; ++i)
7997 for (int j = 0; j < k; ++j)
7998 g.add_edge(a(i), b(j), 1);
7999
8000 return g;
8001}
8002
8003// Returns a mask of length 19938, with weights such that xor-ing with mt19937
8004// outputs yields 0.
8005// O(1).
8006template <typename T> std::vector<bool> mt19937_xor_hash() {
8007 static_assert(std::is_same_v<T, int> or std::is_same_v<T, long long>,
8008 "hack: mt19937_xor_hash: T must be int or long long");
8009
8010 constexpr std::size_t deg = 19937;
8011
8012 std::bitset<deg + 1> a, b, c;
8013 b[deg] = c[deg] = 1;
8014 std::size_t l = 0, shift = 1;
8015 std::mt19937 rng32;
8016 std::mt19937_64 rng64;
8017 for (std::size_t n = 0; n < deg * 2; ++n) {
8018 a >>= 1;
8019 if constexpr (std::is_same_v<T, int>)
8020 a[deg] = rng32() & 1;
8021 else
8022 a[deg] = rng64() & 1;
8023
8024 if ((c & a).count() % 2 == 0) {
8025 ++shift;
8026 continue;
8027 }
8028
8029 std::bitset<deg + 1> oc = c;
8030 c ^= (b >> shift);
8031 if (2 * l <= n) {
8032 l = n + 1 - l;
8033 b = oc;
8034 shift = 1;
8035 } else {
8036 ++shift;
8037 }
8038 }
8039
8040 std::vector<bool> mask(deg + 1);
8041 for (std::size_t i = 0; i <= deg; ++i)
8042 mask[i] = c[i];
8043 return mask;
8044}
8045
8046// Convex polygon that breaks naive rotating calipers for maximum vertex
8047// distance (advances j while dist(i, next(j)) > dist(i, j) instead of using
8048// ccw).
8049// O(1).
8050inline std::vector<geometry::point<double>>
8052 return {
8053 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},
8054 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},
8055 };
8056}
8057
8058namespace detail {
8059
8060// Builds a hack block of order k (length fib(2k+1)).
8061// O(fib(2k+1)).
8062inline std::vector<int> segment_tree_beats_worst_case_block(int k) {
8063 tgen_ensure(k >= 1,
8064 "hack: segment_tree_beats_worst_case: k must be at least 1");
8065
8066 std::vector<int> a(k + 1), b(k + 1);
8067 std::vector<std::vector<int>> vf(k + 1), vg(k + 1);
8068
8069 a[1] = b[1] = 1;
8070 vf[1] = {1};
8071 vg[1] = {1, 0};
8072
8073 for (int i = 2; i <= k; ++i) {
8074 b[i] = b[i - 1] + a[i - 1];
8075 a[i] = b[i] + a[i - 1];
8076 for (int x : vf[i - 1])
8077 vf[i].push_back(x + a[i] + b[i]);
8078 vf[i].push_back(a[i]);
8079 for (int x : vg[i - 1])
8080 vf[i].push_back(x + a[i]);
8081 vg[i] = vf[i];
8082 vg[i].push_back(0);
8083 for (int x : vg[i - 1])
8084 vg[i].push_back(x);
8085 }
8086
8087 vf[k].push_back(0);
8088 return vf[k];
8089}
8090
8091// Appends one update round for the tiled array (offset (round * an) mod L).
8092// O(fib(2k+1)).
8093inline void
8094segment_tree_beats_append_round(std::vector<std::vector<int>> &updates,
8095 int block_len, int an, int bn, int n,
8096 int round) {
8097 const int off = (round * an) % block_len;
8098 const int add_off = (off + block_len - bn) % block_len;
8099 for (int k = 0; k < block_len; ++k) {
8100 const int s = k * block_len * block_len;
8101 const int sub_end = off + an;
8102 if (sub_end <= block_len)
8103 updates.push_back({1, s + off, s + sub_end, bn});
8104 else {
8105 updates.push_back({1, s + off, s + block_len, bn});
8106 updates.push_back({1, s, s + (sub_end - block_len), bn});
8107 }
8108 const int add_end = add_off + bn;
8109 if (add_end <= block_len)
8110 updates.push_back({0, s + add_off, s + add_end, an});
8111 else {
8112 updates.push_back({0, s + add_off, s + block_len, an});
8113 updates.push_back({0, s, s + (add_end - block_len), an});
8114 }
8115 }
8116 updates.push_back({2, 0, n, an});
8117 for (int k = 0; k < block_len; ++k) {
8118 const int s = k * block_len * block_len;
8119 updates.push_back({3, s + (off + an - 1) % block_len, 0});
8120 }
8121}
8122
8123} // namespace detail
8124
8125// Array and updates for worst case of segment tree beats.
8126// O(fib(2k+1)^3 + q).
8127inline std::pair<std::vector<int>, std::vector<std::vector<int>>>
8128segment_tree_beats_worst_case(int k, int q) {
8129 tgen_ensure(k >= 1,
8130 "hack: segment_tree_beats_worst_case: k must be at least 1");
8131 tgen_ensure(k <= 7, "hack: segment_tree_beats_worst_case: k too large");
8132 tgen_ensure(q > 0,
8133 "hack: segment_tree_beats_worst_case: q must be positive");
8134
8135 const auto &fib = math::fibonacci();
8136 const int block_len = fib[k * 2 + 1];
8137 const int an = fib[k * 2];
8138 const int bn = fib[k * 2 - 1];
8139
8140 const int len = block_len;
8141 const int total = len * len * len;
8142
8143 std::vector<int> block = detail::segment_tree_beats_worst_case_block(k);
8144 std::vector<int> arr(total, 0);
8145 for (int x = 0; x < block_len; ++x) {
8146 const int s = x * len * len;
8147 for (int i = 0; i < block_len; ++i)
8148 arr[s + i] = block[i];
8149 }
8150
8151 std::vector<std::vector<int>> updates;
8152 updates.reserve(q);
8153 const int n = total;
8154 for (int round = 0; updates.size() < static_cast<std::size_t>(q); ++round) {
8155 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,
8156 round);
8157 if (updates.size() > static_cast<std::size_t>(q))
8158 updates.resize(q);
8159 }
8160 return {arr, updates};
8161}
8162
8163} // namespace hack
8164
8165/*********************
8166 * *
8167 * MISCELLANEOUS *
8168 * *
8169 *********************/
8170
8171namespace misc {
8172
8173// Generates a uniformly random balanced parentheses sequence with k '(' and k
8174// ')'. Valid means that for no prefix there are more ')' than '('.
8175// O(size).
8176inline std::string gen_parenthesis(int size) {
8177 tgen_ensure(size > 0 and size % 2 == 0,
8178 "misc: parenthesis: size must be a positive even number");
8179
8180 int k = size / 2;
8181 std::string s;
8182 int open = 0, close = 0;
8183
8184 for (int i = 0; i < size; ++i) {
8185 if (open == k) {
8186 s += ')';
8187 ++close;
8188 continue;
8189 }
8190 if (open == close) {
8191 s += '(';
8192 ++open;
8193 continue;
8194 }
8195
8196 long long a = k - open, b = k - close, h = open - close;
8197
8198 // Probability of placing '(':
8199 // P('(') = (k - open) * (h + 2) / ((k - open + k - close) * (h + 1))
8200 // Derived from ballot numbers ratio.
8201 long long num = a * (h + 2);
8202 long long den = (a + b) * (h + 1);
8203
8204 if (next<long long>(1, den) <= num) {
8205 s += '(';
8206 ++open;
8207 } else {
8208 s += ')';
8209 ++close;
8210 }
8211 }
8212
8213 return s;
8214}
8215
8216} // namespace misc
8217
8218} // namespace tgen
std::vector< int > many_by_distribution(int k, const std::vector< T > &distribution)
Returns many random indices with given probabilities.
Definition tgen.h:932
auto shuffled(const C &container)
Shuffles a container.
Definition tgen.h:961
C::value_type pick(const C &container)
Chooses a random element from container.
Definition tgen.h:990
void shuffle(It first, It last)
Shuffles range inplace, for random_access_iterator.
Definition tgen.h:951
T wnext(T left, T right, int w)
Returns a skewed random number in range.
Definition tgen.h:770
It::value_type pick(It first, It last)
Chooses a random element from an iterator range.
Definition tgen.h:980
T next(T right)
Returns a random number smaller than value.
Definition tgen.h:687
size_t next_by_distribution(const std::vector< T > &distribution)
Returns random index with given probabilities.
Definition tgen.h:920
C::value_type pick_by_distribution(const C &container, std::vector< T > distribution)
Chooses a random element with given probabilities.
Definition tgen.h:1000
#define tgen_ensure(cond,...)
Ensures condition is true.
Definition tgen.h:111
T next(T left, T right)
Returns a random number in range.
Definition tgen.h:708
T wnext(T right, int w)
Returns a skewed random number smaller than value.
Definition tgen.h:745
C choose(const C &container, int k)
Chooses elements from container, as in a subsequence fixed length.
Definition tgen.h:1028
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.
Definition tgen.h:6941
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.
Definition tgen.h:6476
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.
Definition tgen.h:6874
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.
Definition tgen.h:7564
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.
Definition tgen.h:7586
wgraph< VWeight, int > vgraph
Vertex-weighted labeled graphs.
Definition tgen.h:6329
graph::value C(int n, bool is_directed=false)
Cycle graph.
Definition tgen.h:6360
wgraph< int, EWeight > egraph
Edge-weighted labeled graphs.
Definition tgen.h:6332
graph::value S(int n)
Star undirected graph.
Definition tgen.h:6384
graph::value K(int n1, int n2)
Complete bipartite undirected graph.
Definition tgen.h:6373
graph::value K(int n)
Complete undirected graph.
Definition tgen.h:6343
wgraph< int, int > graph
Unweighted labeled graphs.
Definition tgen.h:6335
graph::value P(int n, bool is_directed=false)
Path graph.
Definition tgen.h:6349
std::vector< std::pair< int, int > > mo_worst_case(int n, int q)
Query list that forces asymptotic worst-case for Mo's algorithm.
Definition tgen.h:7827
std::vector< bool > mt19937_xor_hash()
Mask that forces a zero XOR hash from std::mt19937 or std::mt19937_64.
Definition tgen.h:8006
egraph< int >::value spfa(int n)
Worst-case for FIFO-SPFA.
Definition tgen.h:7935
egraph< int >::value non_strict_relaxation_dijkstra_bug(int n)
Directed weighted graph for Dijkstra with non-strict relaxation.
Definition tgen.h:7881
std::string abacaba(int n)
Returns the prefix of the infinite word "abacabad...".
Definition tgen.h:7732
std::vector< geometry::point< double > > naive_rotating_calipers_max_dist_bug()
Convex polygon that breaks naive rotating calipers for maximum distance.
Definition tgen.h:8051
std::vector< long long > std_unordered(int size)
List of integers that tries to force collision on std::unordered_set.
Definition tgen.h:7805
std::vector< std::string > string_set_worst_case(int size)
List of strings that have high cost to insert in a std::set.
Definition tgen.h:7860
std::pair< std::string, std::string > unsigned_polynomial_hash()
Returns two strings that force polynomial hash collision for power-of-two mod.
Definition tgen.h:7749
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.
Definition tgen.h:7762
egraph< int >::value dinitz_worst_case(int k, int l)
Flow network for Edmonds-Karp and Dinitz worst-case.
Definition tgen.h:7959
egraph< int >::value stale_heap_dijkstra_bug(int n)
Directed weighted graph for Dijkstra without a stale-heap check.
Definition tgen.h:7911
uint64_t prime_from(uint64_t left)
Computes smallest prime from given value.
Definition tgen.h:2888
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.
Definition tgen.h:2917
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.
Definition tgen.h:3165
uint64_t totient(uint64_t n)
Euler's totient function.
Definition tgen.h:2748
uint64_t congruent_from(uint64_t left, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Computes smallest congruent from given value.
Definition tgen.h:2986
uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod)
Computes largest congruent up to given value.
Definition tgen.h:3074
uint64_t gen_prime(uint64_t left, uint64_t right)
Generates a random prime in given range.
Definition tgen.h:2863
std::vector< uint64_t > factor(uint64_t n)
Factors a number into primes.
Definition tgen.h:2717
int num_divisors(uint64_t n)
Computes the number of divisors of a given number.
Definition tgen.h:2907
bool is_prime(uint64_t n)
Checks if a number is prime.
Definition tgen.h:2465
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.
Definition tgen.h:3099
constexpr int FFT_MOD
FFT/NTT mod.
Definition tgen.h:3080
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.
Definition tgen.h:2976
uint64_t prime_upto(uint64_t right)
Computes largest prime up to given value.
Definition tgen.h:2897
uint64_t highly_composite_upto(uint64_t right)
Largest highly composite number up to given number.
Definition tgen.h:2853
uint64_t congruent_upto(uint64_t right, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Computes largest congruent up to given value.
Definition tgen.h:3034
std::vector< std::pair< uint64_t, int > > factor_by_prime(uint64_t n)
Factors a number into primes and its powers.
Definition tgen.h:2727
const std::vector< uint64_t > & fibonacci()
Fetches Fibonacci numbers.
Definition tgen.h:3083
uint64_t modular_inverse(uint64_t a, uint64_t mod)
Computes modular inverse.
Definition tgen.h:2742
uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod)
Computes smallest congruent from given value.
Definition tgen.h:3025
const std::vector< uint64_t > & highly_composites()
Fetches highly composite numbers.
Definition tgen.h:2813
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.
Definition tgen.h:3354
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.
Definition tgen.h:3263
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.
Definition tgen.h:2932
std::pair< uint64_t, uint64_t > prime_gap_upto(uint64_t right)
Largest prime gap up to given number.
Definition tgen.h:2794
std::string gen_parenthesis(int size)
Generates a random valid parenthesis sequence.
Definition tgen.h:8176
T opt(const std::string &key, std::optional< T > default_value=std::nullopt)
Gets opt by key.
Definition tgen.h:1488
void set_compiler(compiler_value compiler)
Sets compiler.
Definition tgen.h:1271
T opt(size_t index, std::optional< T > default_value=std::nullopt)
Gets opt by key.
Definition tgen.h:1474
bool has_opt(std::size_t index)
Checks if opt at some index exists.
Definition tgen.h:1456
bool has_opt(const std::string &key)
Checks if opt with some key exists.
Definition tgen.h:1462
void set_cpp_version(int version)
Sets C++ version.
Definition tgen.h:1252
void register_gen(std::optional< long long > seed=std::nullopt)
Sets up the generator without arguments.
Definition tgen.h:1515
void register_gen(int argc, char **argv)
Sets up the generator.
Definition tgen.h:1504
wtree< VWeight, int > vtree
Vertex-weighted labeled trees.
Definition tgen.h:4979
wtree< int, EWeight > etree
Edge-weighted labeled trees.
Definition tgen.h:4982
wtree< int, int > tree
Unweighted labeled trees.
Definition tgen.h:4985
Compiler identity and version.
Definition tgen.h:283
Distinct generator for containers.
Definition tgen.h:1186
auto gen_list(int size)
Generates a list of several distinct elements.
Definition tgen.h:1207
T gen()
Generates a distinct random element from the container.
Definition tgen.h:1203
distinct_container(const C &container)
Creates distinct generator for elements of the given container.
Definition tgen.h:1192
auto gen_all()
Generates all distinct elements left to generate.
Definition tgen.h:1216
size_t size() const
Returns the number of elements left to generate.
Definition tgen.h:1199
Distinct generator for integral ranges.
Definition tgen.h:1050
auto gen_list(int count)
Generates a list of several distinct values.
Definition tgen.h:1089
distinct_range(T left, T right)
Creates distinct generator for values in given range.
Definition tgen.h:1059
auto gen_all()
Generates all distinct values left to generate.
Definition tgen.h:1114
T gen()
Generates a distinct random value in the defined range.
Definition tgen.h:1068
T size() const
Returns the number of values left to generate.
Definition tgen.h:1063
Distinct generator for discrete uniform functions.
Definition tgen.h:321
distinct(Func func, Args... args)
Generates a distinct generator of a discrete uniform function.
Definition tgen.h:327
auto gen_list(int size)
Generates a list of several distinct values.
Definition tgen.h:361
bool empty()
Checks if there is nothing left to generate.
Definition tgen.h:372
auto gen_all()
Generates all distinct values left to generate.
Definition tgen.h:375
auto gen()
Generates a distinct value.
Definition tgen.h:349
Base class for generators (should not be instantiated).
Definition tgen.h:408
auto gen_list(int size, Args &&...args) const
Generates a list of several generation calls.
Definition tgen.h:411
auto gen_until(Pred predicate, int max_tries, Args &&...args) const
Generates a random value from the valid set until a condition is met.
Definition tgen.h:423
auto distinct(Args &&...args) const
Creates distinct generator for current generator.
Definition tgen.h:442
Base class for generator values (should not be instantiated).
Definition tgen.h:465
bool operator<(const Val &rhs) const
Definition tgen.h:468
Point on the plane.
Definition tgen.h:6395
T x() const
x coordinate.
Definition tgen.h:6412
bool operator==(const point &p) const
Coordinate-wise equality.
Definition tgen.h:6435
product_t operator*(const point &p) const
Dot product.
Definition tgen.h:6453
product_t operator^(const point &p) const
Cross product.
Definition tgen.h:6460
point operator*(T c) const
Scalar multiplication.
Definition tgen.h:6450
point operator-(const point &p) const
Vector subtraction.
Definition tgen.h:6445
point(T x=0, T y=0)
Constructs a point.
Definition tgen.h:6409
T y() const
y coordinate.
Definition tgen.h:6415
bool operator<(const point &p) const
Lexicographic order.
Definition tgen.h:6428
point operator+(const point &p) const
Vector addition.
Definition tgen.h:6440
List value.
Definition tgen.h:1676
int size() const
Returns the size of the list value.
Definition tgen.h:1689
value(const std::vector< T > &vec)
Creates a list value from a std::vector.
Definition tgen.h:1685
value & sort()
Sorts the list in non-decreasing order.
Definition tgen.h:1705
auto to_std() const
Converts the list to a std::vector.
Definition tgen.h:1787
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:1719
value choose(int k) const
Chooses a uniformly random subsequence of given length.
Definition tgen.h:1761
value operator+(const value &rhs) const
Concatenates two lists.
Definition tgen.h:1726
T & operator[](int idx)
Accesses the element at some position of the list.
Definition tgen.h:1692
value & reverse()
Reverses the list.
Definition tgen.h:1712
T pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the list with given probabilities.
Definition tgen.h:1748
value & shuffle()
Shuffles the list in place.
Definition tgen.h:1735
T pick() const
Returns a uniformly random element.
Definition tgen.h:1743
List generator.
Definition tgen.h:1539
list & different(int idx_1, int idx_2)
Restricts generator s.t. values at two indices are different.
Definition tgen.h:1653
list & equal(int idx_1, int idx_2)
Restricts generator s.t. values at two indices are equal.
Definition tgen.h:1606
list & all_different()
Restricts generator s.t. all values are different.
Definition tgen.h:1668
list & equal_range(int left, int right)
Restricts generator s.t. all values at index range are equal.
Definition tgen.h:1632
list(int size, std::set< T > values)
Creates list generator defined by value set.
Definition tgen.h:1567
value gen() const
Generates a uniformly random value from the set of valid lists.
Definition tgen.h:1802
list & all_equal()
Restricts generator s.t. all values are equal.
Definition tgen.h:1641
list & different(std::set< int > indices)
Restricts generator s.t. all values in index set are different.
Definition tgen.h:1646
list & different_range(int left, int right)
Restricts generator s.t. all values at index range are different.
Definition tgen.h:1659
list(int size, T value_left, T value_right)
Creates list generator defined by size and range of values.
Definition tgen.h:1559
list & fix(int idx, T val)
Restricts generator s.t. value at index is fixed.
Definition tgen.h:1579
list & equal(std::set< int > indices)
Restricts generator s.t. all values in index set are equal.
Definition tgen.h:1622
Pair value.
Definition tgen.h:4198
T second() const
Returns the second element of a pair value.
Definition tgen.h:4210
value(const T &first, const T &second)
Creates a pair value from first and second values.
Definition tgen.h:4206
value(const std::pair< T, T > &pair)
Creates a pair value from a std::pair.
Definition tgen.h:4205
auto to_std() const
Converts the pair to a std::pair.
Definition tgen.h:4224
T first() const
Returns the first element of a pair value.
Definition tgen.h:4209
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:4213
Pair generator.
Definition tgen.h:4141
value gen() const
Generates a uniformly random value from the set of valid pairs.
Definition tgen.h:4237
pair & neq()
Restricts generator s.t. first is not equal to second.
Definition tgen.h:4168
pair & leq()
Restricts generator s.t. first is less than or equal to second.
Definition tgen.h:4186
pair & lt()
Restricts generator s.t. first is less than second.
Definition tgen.h:4174
pair & gt()
Restricts generator s.t. first is greater than second.
Definition tgen.h:4180
pair(T both_left, T both_right)
Creates pair generator defined by range of values for both first and second.
Definition tgen.h:4158
pair & eq()
Restricts generator s.t. first is equal to second.
Definition tgen.h:4162
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.
Definition tgen.h:4149
pair & geq()
Restricts generator s.t. first is greater than or equal to second.
Definition tgen.h:4192
Permutation value.
Definition tgen.h:2229
value & add_1()
Adds 1 for printing.
Definition tgen.h:2314
std::vector< int > to_std() const
Converts the permutation to a std::vector.
Definition tgen.h:2356
const int & operator[](int idx) const
Returns the image at some position of the permutation.
Definition tgen.h:2258
value & sort()
Sorts the permutation in non-decreasing order.
Definition tgen.h:2282
int parity() const
Parity of the permutation.
Definition tgen.h:2266
int pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the permutation with given probabilities.
Definition tgen.h:2334
int pick() const
Returns a uniformly random element.
Definition tgen.h:2329
value & reverse()
Reverses the permutation.
Definition tgen.h:2290
value(const std::vector< int > &vec)
Creates a permutation value from a std::vector.
Definition tgen.h:2237
int size() const
Returns the size of the permutation value.
Definition tgen.h:2255
value & shuffle()
Shuffles the permutation.
Definition tgen.h:2321
value & inverse()
Inverse of the permutation.
Definition tgen.h:2297
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:2307
Permutation generator.
Definition tgen.h:2197
value gen() const
Generates a uniformly random value from the set of valid permutations.
Definition tgen.h:2361
permutation & cycles(const std::vector< int > &cycle_sizes)
Restricts generator s.t. cycle sizes are fixed.
Definition tgen.h:2216
permutation(int size)
Creates permutation generator defined by size.
Definition tgen.h:2203
permutation & fix(int idx, int val)
Restricts generator s.t. value at index is fixed.
Definition tgen.h:2208
Printer helper for printing containers or sequential generator elements as columns.
Definition tgen.h:614
print_cols(const Args &...args)
Creates a printer object that prints as columns.
Definition tgen.h:617
Printer helper for standard types.
Definition tgen.h:487
print(const T &val, char sep=' ')
Creates a printer object.
Definition tgen.h:490
Printer helper for standard types, printing on a new line.
Definition tgen.h:589
println(const T &val, char sep=' ')
Creates a printer object that prints on a new line.
Definition tgen.h:591
String value.
Definition tgen.h:3805
char pick() const
Returns a uniformly random element.
Definition tgen.h:3877
char pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the string with given probabilities.
Definition tgen.h:3882
value choose(int k) const
Chooses a uniformly random subsequence of given length.
Definition tgen.h:3895
value & lowercase()
Sets all characters to lowercase.
Definition tgen.h:3847
value & reverse()
Reverses the string.
Definition tgen.h:3840
int size() const
Returns the size of the string value.
Definition tgen.h:3817
value(const std::string &str)
Creates a string value from a std::string.
Definition tgen.h:3812
value & shuffle()
Shuffles the string.
Definition tgen.h:3869
char & operator[](int idx)
Accesses the character at some position of the string.
Definition tgen.h:3820
value & uppercase()
Sets all characters to uppercase.
Definition tgen.h:3855
value operator+(const value &rhs) const
Concatenates two strings.
Definition tgen.h:3863
std::string to_std() const
Converts the string to a std::string.
Definition tgen.h:3916
value & sort()
Sorts the characters in non-decreasing order.
Definition tgen.h:3833
String generator.
Definition tgen.h:3697
str & different(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are different.
Definition tgen.h:3784
str & palindrome(int left, int right)
Restricts generator s.t. range is a palindrome.
Definition tgen.h:3760
value gen() const
Generates a uniformly random value from the set of valid strings.
Definition tgen.h:3922
str(int size, char value_left='a', char value_right='z')
Creates string generator defined by size and range of characters.
Definition tgen.h:3704
str & different(std::set< int > indices)
Restricts generator s.t. all characters in index set are different.
Definition tgen.h:3777
str(const std::string &regex, Args &&...args)
Creates string generator defined by regex.
Definition tgen.h:3717
str & equal(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are equal.
Definition tgen.h:3739
str & equal(std::set< int > indices)
Restricts generator s.t. all characters in index set are equal.
Definition tgen.h:3732
str & equal_range(int left, int right)
Restricts generator s.t. all characters at index range are equal.
Definition tgen.h:3746
str & fix(int idx, char character)
Restricts generator s.t. character at index is fixed.
Definition tgen.h:3725
str & all_equal()
Restricts generator s.t. all values are equal.
Definition tgen.h:3753
str & different_range(int left, int right)
Restricts generator s.t. all characters at index range are different.
Definition tgen.h:3791
str & palindrome()
Restricts generator s.t. string is a palindrome.
Definition tgen.h:3770
str & all_different()
Restricts generator s.t. all characters are different.
Definition tgen.h:3798
str(int size, std::set< char > chars)
Creates string generator defined by character set.
Definition tgen.h:3711
Sampler for repeated draws from a fixed weighted distribution.
Definition tgen.h:824
size_t next() const
Generates a random index with probability proportional to the distribution.
Definition tgen.h:907
weighted_sampler(const std::vector< T > &distribution)
Creates a weighted sampler from a probability distribution.
Definition tgen.h:841
Labeled graph value.
Definition tgen.h:5161
value & print_nm()
Prints number of vertices and edges before edge list.
Definition tgen.h:5337
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
Definition tgen.h:5280
value operator!() const
Graph complement of unweighted graph.
Definition tgen.h:5712
std::tuple< int, int, std::vector< std::set< int > > > to_std() const
Converts the graph to std types.
Definition tgen.h:5801
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
Definition tgen.h:5347
value & add_1()
Adds 1 for printing.
Definition tgen.h:5330
int n() const
Number of vertices.
Definition tgen.h:5262
value operator+(const value &rhs) const
Concatenates two graphs (disjoint union).
Definition tgen.h:5746
value & disjoint_union(const value &rhs)
Disjoint union with another graph.
Definition tgen.h:5583
int m() const
Number of edges.
Definition tgen.h:5265
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another graph at given vertex pairs.
Definition tgen.h:5506
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
Definition tgen.h:5285
value(const std::vector< std::set< int > > &adj, bool is_directed=false)
Builds a graph from an adjacency list.
Definition tgen.h:5180
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.
Definition tgen.h:5201
wgraph< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
Definition tgen.h:5292
const std::vector< std::set< int > > & adj() const
Adjacency list.
Definition tgen.h:5271
value & add_vertices(int k, std::optional< std::vector< VWeight > > new_vertex_weights=std::nullopt)
Adds new isolated vertices.
Definition tgen.h:5418
value & random_connected_subgraph(int num_edges)
Random subgraph with a fixed number of edges that keeps components connected.
Definition tgen.h:5622
value(const typename wtree< VWeight, EWeight >::value &t)
Builds an undirected graph from a tree.
Definition tgen.h:5232
value & random_subgraph(int num_edges)
Random subgraph with a fixed number of edges.
Definition tgen.h:5589
value & edge_weighted()
Enables edge-weighted mode on an edgeless graph.
Definition tgen.h:5317
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.
Definition tgen.h:5479
bool is_directed() const
If the graph is directed.
Definition tgen.h:5268
value & add_edge(int u, int v, std::optional< EWeight > w=std::nullopt)
Adds an edge between two vertices.
Definition tgen.h:5445
value & shuffle()
Shuffles all vertices and edge order.
Definition tgen.h:5413
wgraph< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Definition tgen.h:5306
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Definition tgen.h:5277
Labeled weighted graph generator.
Definition tgen.h:5125
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.
Definition tgen.h:5135
static value gen_bipartite(int n1, int n2, int m, bool connected=false)
Generates a random bipartite graph.
Definition tgen.h:6148
value get_connected() const
Random connected undirected graph extending preset edges.
Definition tgen.h:5868
value gen() const
Generates a uniformly random graph satisfying the constraints.
Definition tgen.h:5844
wgraph & add_edge(int u, int v)
Adds a preset edge that must appear in the generated graph.
Definition tgen.h:5143
value get_acyclic() const
Random directed acyclic graph extending preset edges.
Definition tgen.h:5942
static value gen_skewed(int n, int m, int elongation, int spread, bool is_directed=false)
Random skewed connected graph (large diameter).
Definition tgen.h:6045
wgraph & add_edges_from(const value &rhs)
Adds all edges from another graph as preset edges.
Definition tgen.h:5831
Labeled tree value.
Definition tgen.h:4387
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another tree at given vertex pairs.
Definition tgen.h:4690
value & add_1()
Adds 1 for printing.
Definition tgen.h:4528
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Definition tgen.h:4474
value(int n, const std::vector< std::pair< int, int > > &edges)
Builds a tree from a vertex count and an edge list.
Definition tgen.h:4424
value(const typename wgraph< VWeight, EWeight >::value &g)
Builds a tree from a graph via a Kruskal-like random spanning tree.
Definition tgen.h:6280
value & print_parents(int root=-1)
Prints in parent format instead of edge list.
Definition tgen.h:4544
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
Definition tgen.h:4477
value & edge_weighted()
Enables edge-weighted mode on an edgeless tree.
Definition tgen.h:4515
int n() const
Returns the number of vertices.
Definition tgen.h:4468
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
Definition tgen.h:4556
const std::vector< std::set< int > > & adj() const
Adjacency list.
Definition tgen.h:4471
value(const std::vector< std::set< int > > &adj)
Builds a tree from an adjacency list.
Definition tgen.h:4404
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
Definition tgen.h:4482
value & shuffle()
Shuffles vertices and edge order.
Definition tgen.h:4625
std::pair< int, std::vector< std::set< int > > > to_std() const
Converts the tree to a std types.
Definition tgen.h:4850
wtree< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
Definition tgen.h:4489
value & print_n()
Prints the number of vertices before the tree.
Definition tgen.h:4535
value & link(const value &rhs, int new_u, int new_v, std::optional< EWeight > new_w=std::nullopt)
Links two trees by an edge.
Definition tgen.h:4663
wtree< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Definition tgen.h:4503
Labeled weighted tree generator.
Definition tgen.h:4360
wtree & add_edge(int u, int v)
Restricts generator s.t. some edge is present.
Definition tgen.h:4372
static value gen_skewed(int n, int elongation)
Random skewed tree (large diameter).
Definition tgen.h:4944
value gen() const
Generates a uniformly random value from the set of valid trees.
Definition tgen.h:4887
wtree(int n)
Creates a tree generator with specified number of vertices.
Definition tgen.h:4366
static value gen_kruskal(int n)
Kruskal-like random labeled tree.
Definition tgen.h:4954