← 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 p = gen_prime(detail::kth_root_floor(left, root),
2923 detail::kth_root_floor(right, root));
2924 return *detail::expo(p, root, right);
2925}
2926
2927// O(|mods| + log (right)).
2928// |rems| = |mods|.
2929// rems_i < mods_i.
2930inline uint64_t gen_congruent(uint64_t left, uint64_t right,
2931 std::vector<uint64_t> rems,
2932 std::vector<uint64_t> mods) {
2933 if (left > right)
2934 throw detail::there_is_no_in_range_error("congruent number", left,
2935 right);
2936 tgen_ensure(rems.size() == mods.size(),
2937 "math: number of remainders and mods must be the same");
2938 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
2939
2940 detail::crt crt;
2941 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
2942 tgen_ensure(rems[i] < mods[i],
2943 "math: remainder must be smaller than the mod");
2944 crt = crt * detail::crt(rems[i], mods[i]);
2945
2946 if (crt.a == -1)
2947 throw detail::there_is_no_in_range_error("congruent number", left,
2948 right);
2949 if (crt.m > right) {
2950 if (!(left <= crt.a and crt.a <= right))
2951 throw detail::there_is_no_in_range_error("congruent number",
2952 left, right);
2953
2954 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
2955 if (crt.a % mods[j] != rems[j])
2956 throw detail::there_is_no_in_range_error("congruent number",
2957 left, right);
2958 return crt.a;
2959 }
2960 }
2961
2962 uint64_t k_min = crt.a >= left ? 0 : ((left - crt.a) + crt.m - 1) / crt.m;
2963 uint64_t k_max = (right - crt.a) / crt.m;
2964
2965 if (k_min > k_max)
2966 throw detail::there_is_no_in_range_error("congruent number", left,
2967 right);
2968
2969 return crt.a + next(k_min, k_max) * crt.m;
2970}
2971
2972// O(log (right)).
2973// rem < mod.
2974inline uint64_t gen_congruent(uint64_t left, uint64_t right, uint64_t rem,
2975 uint64_t mod) {
2976 return gen_congruent(left, right, std::vector<uint64_t>({rem}),
2977 std::vector<uint64_t>({mod}));
2978}
2979
2980// First congruent number >= left.
2981// O(|mods| + log (left)).
2982// |rems| = |mods|.
2983// rems_i < mods_i.
2984inline uint64_t congruent_from(uint64_t left, std::vector<uint64_t> rems,
2985 std::vector<uint64_t> mods) {
2986 tgen_ensure(rems.size() == mods.size(),
2987 "math: number of remainders and mods must be the same");
2988 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
2989
2990 detail::crt crt;
2991 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
2992 tgen_ensure(rems[i] < mods[i],
2993 "math: remainder must be smaller than the mod");
2994 crt = crt * detail::crt(rems[i], mods[i]);
2995
2996 if (crt.a == -1)
2997 throw detail::there_is_no_from_error("congruent number", left);
2998 if (crt.m > std::numeric_limits<uint64_t>::max()) {
2999 if (crt.a < left)
3000 throw detail::error(
3001 "math: congruent number does not exist or is too large");
3002
3003 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
3004 if (crt.a % mods[j] != rems[j])
3005 throw detail::error("math: congruent number does "
3006 "not exist or is too large");
3007 return crt.a;
3008 }
3009 }
3010
3011 uint64_t k = 0;
3012 if (crt.a < left)
3013 k = ((left - crt.a) + crt.m - 1) / crt.m;
3014 detail::i128 result = crt.a + k * crt.m;
3015
3016 if (result > std::numeric_limits<uint64_t>::max())
3017 throw detail::error("math: congruent number is too large");
3018 return result;
3019}
3020
3021// O(log (left))
3022// rem < mod.
3023inline uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod) {
3024 return congruent_from(left, std::vector<uint64_t>{rem},
3025 std::vector<uint64_t>{mod});
3026}
3027
3028// Last congruent number <= right.
3029// O(|mods| + log (right)).
3030// |rems| = |mods|.
3031// rems_i < mods_i.
3032inline uint64_t congruent_upto(uint64_t right, std::vector<uint64_t> rems,
3033 std::vector<uint64_t> mods) {
3034 tgen_ensure(rems.size() == mods.size(),
3035 "math: number of remainders and mods must be the same");
3036 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
3037
3038 detail::crt crt;
3039 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
3040 tgen_ensure(rems[i] < mods[i],
3041 "math: remainder must be smaller than the mod");
3042
3043 crt = crt * detail::crt(rems[i], mods[i]);
3044
3045 if (crt.a == -1)
3046 throw detail::there_is_no_upto_error("congruent number", right);
3047 if (crt.m > right) {
3048 if (!(crt.a <= right))
3049 throw detail::there_is_no_upto_error("congruent number", right);
3050
3051 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
3052 if (crt.a % mods[j] != rems[j])
3053 throw detail::there_is_no_upto_error("congruent number",
3054 right);
3055 return crt.a;
3056 }
3057 }
3058
3059 if (crt.a > right)
3060 throw detail::there_is_no_upto_error("congruent number", right);
3061
3062 uint64_t k = (right - crt.a) / crt.m;
3063 detail::i128 result = crt.a + k * crt.m;
3064
3065 if (result < 0)
3066 throw detail::there_is_no_upto_error("congruent number", right);
3067 return result;
3068}
3069
3070// O(log r)
3071// rem < mod.
3072inline uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod) {
3073 return congruent_upto(right, std::vector<uint64_t>{rem},
3074 std::vector<uint64_t>{mod});
3075}
3076
3077// Mod used for FFT/NTT.
3078inline constexpr int FFT_MOD = 998244353;
3079
3080// Fibonacci sequence up to 2^64.
3081inline const std::vector<uint64_t> &fibonacci() {
3082 static const std::vector<uint64_t> fib = [] {
3083 std::vector<uint64_t> v = {0, 1};
3084 while (v.back() <=
3085 std::numeric_limits<uint64_t>::max() - v[v.size() - 2])
3086 v.push_back(v.back() + v[v.size() - 2]);
3087 return v;
3088 }();
3089 return fib;
3090}
3091
3092// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3093// O(n).
3094// 0 < n.
3095// 0 < part_left.
3096inline std::vector<int>
3097gen_partition(int n, int part_left = 1,
3098 std::optional<int> part_right = std::nullopt) {
3099 if (!part_right.has_value())
3100 part_right = n;
3101 part_right = std::min(*part_right, n);
3102 tgen_ensure(n > 0 and part_left > 0,
3103 "math: invalid parameters to gen_partition");
3104 tgen_ensure(part_left <= n and *part_right > 0, "math: no such partition");
3105
3106 // dp[i] = log(number of ways to add to i).
3107 std::vector<long double> dp(n + 1, detail::LOG_ZERO);
3108 dp[0] = detail::LOG_ONE;
3109 long double window = detail::LOG_ZERO;
3110 for (int i = 1; i <= n; ++i) {
3111 if (i >= part_left)
3112 window = detail::add_log_space(window, dp[i - part_left]);
3113 if (i >= *part_right + 1)
3114 window = detail::sub_log_space(window, dp[i - *part_right - 1]);
3115 dp[i] = window;
3116 }
3117 tgen_ensure(dp[n] >= 0, "math: no such partition");
3118
3119 // Crazy math tricks ahead.
3120 auto dp_pref = dp;
3121 for (int i = 1; i <= n; ++i)
3122 dp_pref[i] = detail::add_log_space(dp_pref[i - 1], dp[i]);
3123
3124 std::vector<int> part;
3125 int sum = n;
3126 while (sum > 0) {
3127 // Will generate a number such that what remains is in [l, r].
3128 int l = std::max(0, sum - *part_right), r = sum - part_left;
3129 detail::tgen_ensure_against_bug(r >= 0, "math: r < 0 in gen_partition");
3130
3131 int nxt_sum = std::min(sum, r);
3132 long double random = next<long double>(0, 1);
3133
3134 // We generate a value X (log space), and then choose nxt_sum such
3135 // that dp_pref[nxt_sum-1] < X <= dp_pref[nxt_sum].
3136
3137 // Math hack:
3138 // Let A = pref[l-1], B = pref[r], U = rand().
3139 // X = log[exp(A) + U * (exp(B) - exp(A))]
3140 // = log{exp(B) * [exp(A) / exp(B) + U * (1 - exp(A) / exp(B))]}
3141 // = B + log[exp(A - B) + U - U * exp(A - B))]
3142 // = B + log[U + (1 - U) * exp(A - B)].
3143 long double val_l = l ? dp_pref[l - 1] : detail::LOG_ZERO,
3144 val_r = dp_pref[r];
3145 while (nxt_sum > l and
3146 dp_pref[nxt_sum - 1] >=
3147 val_r + detail::log_space(random +
3148 (1 - random) * exp(val_l - val_r)))
3149 --nxt_sum;
3150
3151 part.push_back(sum - nxt_sum);
3152 sum = nxt_sum;
3153 }
3154
3155 return part;
3156}
3157
3158// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3159// O(n) time/memory if part_right is not set, O(n * k) time/memory otherwise.
3160// 0 < k <= n.
3161// 0 <= part_left.
3162inline std::vector<int>
3163gen_partition_fixed_size(int n, int k, int part_left = 0,
3164 std::optional<int> part_right = std::nullopt) {
3165 if (!part_right.has_value())
3166 part_right = n;
3167 part_right = std::min(*part_right, n);
3168 tgen_ensure(0 < k and k <= n and part_left >= 0,
3169 "math: invalid parameters to gen_partition_fixed_size");
3170 tgen_ensure(static_cast<long long>(k) * part_left <= n and
3171 n <= static_cast<long long>(k) * (*part_right),
3172 "math: no such partition");
3173
3174 // What we need to distribute to the parts.
3175 int s = n - k * part_left;
3176
3177 std::vector<int> part(k);
3178 if (*part_right == n) {
3179 // Stars and bars - O(n).
3180 std::vector<int> cuts = {-1};
3181
3182 int total = s + k - 1, bars = k - 1;
3183 for (int i = 0; i < total and bars > 0; ++i)
3184 if (next<long double>(0, 1) <
3185 static_cast<long double>(bars) / (total - i)) {
3186 cuts.push_back(i);
3187 --bars;
3188 }
3189 cuts.push_back(total);
3190
3191 // Recovers parts.
3192 for (int i = 0; i < k; ++i)
3193 part[i] = cuts[i + 1] - cuts[i] - 1;
3194 } else {
3195 // DP with log trick - O(nk).
3196 int u = *part_right - part_left;
3197
3198 // dp[i][j] = log(#ways to fill i parts with sum j)
3199 std::vector<std::vector<long double>> dp(
3200 k + 1, std::vector<long double>(s + 1, detail::LOG_ZERO));
3201 dp[0][0] = detail::LOG_ONE;
3202
3203 for (int i = 1; i <= k; ++i) {
3204 std::vector<long double> pref = dp[i - 1];
3205 for (int j = 1; j <= s; ++j)
3206 pref[j] = detail::add_log_space(pref[j - 1], dp[i - 1][j]);
3207
3208 for (int j = 0; j <= s; ++j) {
3209 dp[i][j] = pref[j];
3210 if (j >= u + 1)
3211 dp[i][j] = detail::sub_log_space(dp[i][j], pref[j - u - 1]);
3212 }
3213 }
3214
3215 // Recovers parts backwards.
3216 int left_to_distribute = s;
3217 for (int i = k; i >= 1; --i) {
3218 long double log_total = detail::LOG_ZERO;
3219 for (int j = 0; j <= u and j <= left_to_distribute; ++j)
3220 log_total = detail::add_log_space(
3221 log_total, dp[i - 1][left_to_distribute - j]);
3222 detail::tgen_ensure_against_bug(
3223 log_total != detail::LOG_ZERO,
3224 "math: total == 0 in gen_partition_fixed_size");
3225
3226 // Now we choose a number with probability proportional to
3227 // dp[i-1][.].
3228
3229 // log(rand() * total) = log(rand()) + log(total).
3230 long double random =
3231 detail::log_space(next<long double>(0, 1)) + log_total;
3232
3233 long double cur_prob = detail::LOG_ZERO;
3234 int chosen = 0;
3235 for (int j = 0; j <= u and j <= left_to_distribute; ++j) {
3236 cur_prob = detail::add_log_space(
3237 cur_prob, dp[i - 1][left_to_distribute - j]);
3238 if (random < cur_prob) {
3239 chosen = j;
3240 break;
3241 }
3242 }
3243
3244 part[k - i] = chosen;
3245 left_to_distribute -= chosen;
3246 }
3247 }
3248
3249 for (int &i : part)
3250 i += part_left;
3251 return part;
3252}
3253
3254// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3255// Inspired by jngen rndm.partition: random delimiters, sort, gap recovery;
3256// omits jngen's part reordering, shuffles, and two-pass redistribution.
3257// 0 < k <= n.
3258// 0 <= part_left.
3259// Not uniformly random; optimized for speed.
3260// O(k log k).
3262 uint64_t n, int k, uint64_t part_left = 0,
3263 std::optional<uint64_t> part_right = std::nullopt) {
3264 if (!part_right.has_value())
3265 part_right = n;
3266 part_right = std::min(*part_right, n);
3267
3268 detail::u128 n128 = n;
3269 detail::u128 k128 = k;
3270 detail::u128 part_left128 = part_left;
3271 detail::u128 part_right128 = *part_right;
3272
3273 tgen_ensure(k > 0 and k128 <= n128,
3274 "math: invalid parameters to gen_partition_fixed_size_fast");
3275 tgen_ensure(part_right128 >= part_left128 and
3276 k128 * part_left128 <= n128 and
3277 k128 * part_right128 >= n128,
3278 "math: no such partition");
3279
3280 uint64_t slack_total = n128 - k128 * part_left128;
3281 uint64_t slack_max = part_right128 - part_left128;
3282
3283 std::vector<uint64_t> part(k);
3284 if (k == 1) {
3285 part[0] = slack_total;
3286 } else {
3287 std::vector<uint64_t> cuts(k - 1);
3288 for (uint64_t &d : cuts)
3289 d = next<uint64_t>(0, slack_total);
3290 std::sort(cuts.begin(), cuts.end());
3291
3292 uint64_t prev = 0;
3293 for (int i = 0; i + 1 < k; ++i) {
3294 part[i] = cuts[i] - prev;
3295 prev = cuts[i];
3296 }
3297 part[k - 1] = slack_total - prev;
3298 }
3299
3300 auto add_part_left = [part_left](uint64_t x) -> uint64_t {
3301 detail::u128 val = x + part_left;
3302 detail::tgen_ensure_against_bug(
3303 val <= std::numeric_limits<uint64_t>::max(),
3304 "math: part + part_left exceeds uint64_t in "
3305 "gen_partition_fixed_size_fast");
3306 return val;
3307 };
3308
3309 if (slack_max >= slack_total) {
3310 for (uint64_t &x : part)
3311 x = add_part_left(x);
3312 return part;
3313 }
3314
3315 detail::u128 remaining = 0;
3316 for (uint64_t &x : part) {
3317 if (x > slack_max) {
3318 remaining += x - slack_max;
3319 x = slack_max;
3320 }
3321 x = add_part_left(x);
3322 }
3323
3324 if (remaining > 0) {
3325 for (uint64_t &x : part) {
3326 if (x < *part_right && remaining > 0) {
3327 detail::u128 room = *part_right - x;
3328 detail::u128 add = std::min(remaining, room);
3329 detail::u128 val = x + add;
3330 detail::tgen_ensure_against_bug(
3331 val <= *part_right,
3332 "math: part exceeds part_right after redistribution in "
3333 "gen_partition_fixed_size_fast");
3334 x = val;
3335 remaining -= add;
3336 }
3337 }
3338 detail::tgen_ensure_against_bug(
3339 remaining == 0, "math: remaining mass after redistribution in "
3340 "gen_partition_fixed_size_fast");
3341 }
3342
3343 return part;
3344}
3345
3346// Random partition of elements into k ordered groups (input order preserved).
3347// If max_size is unset, part sizes are uniform via gen_partition_fixed_size.
3348// If max_size is set, uses gen_partition_fixed_size_fast (not uniform).
3349// O(n) if max_size is unset; O(n + k log k) if max_size is set.
3350template <typename T>
3351std::vector<std::vector<T>>
3352partition_elements(std::vector<T> elements, int k, int min_size = 0,
3353 std::optional<uint64_t> max_size = std::nullopt) {
3354 size_t n = elements.size();
3355 tgen_ensure(k > 0, "math: partition_elements: k must be positive");
3356 tgen_ensure(min_size >= 0,
3357 "math: partition_elements: min_size must be non-negative");
3358
3359 std::vector<uint64_t> sizes;
3360 if (max_size.has_value()) {
3361 sizes = gen_partition_fixed_size_fast(n, k, min_size, max_size);
3362 } else {
3363 for (int sz : gen_partition_fixed_size(n, k, min_size))
3364 sizes.push_back(sz);
3365 }
3366
3367 std::vector<std::vector<T>> groups;
3368 groups.reserve(k);
3369 size_t pos = 0;
3370 for (uint64_t sz : sizes) {
3371 groups.emplace_back(elements.begin() + pos,
3372 elements.begin() + pos + sz);
3373 pos += sz;
3374 }
3375 return groups;
3376}
3377
3378}; // namespace math
3379
3380/**************
3381 * *
3382 * STRING *
3383 * *
3384 **************/
3385
3386namespace detail {
3387
3388/*
3389 * Regex.
3390 *
3391 * Compatible with testlib's regex.
3392 *
3393 * Operations:
3394 * - A single character yields itself ("a", "3").
3395 * - A list of characters inside square braces yields any a random element
3396 * from the list ("[abc123]").
3397 * - A range of characters is equivalent to listing them ("[a-z1-9A-Z]").
3398 * - A pattern followed by {n} yields the pattern repeated n times ("a{3}").
3399 * - A pattern followed by {l,r} yields the pattern repeated between l and r
3400 * times, uniformly at random ("a{3,5}").
3401 * - A list of patterns separated by | yields a random pattern from the
3402 * list, uniformly at random ("abc|def|ghi").
3403 * - Parentheses can be used for grouping ("a((a|b){3})").
3404 *
3405 * Examples:
3406 * 1. str("[1-9][0-9]{1,2}") generates two- or three-digit numbers.
3407 * 2. str("a[b-d]{2}|e") generates "e" or a random string of length 3, with
3408 * the first character being 'a' and the second and
3409 * third characters being 'b', 'c', or 'd'.
3410 * 3. str("[1-9][0-9]{%d}", n-1) generates n-digit numbers.
3411 *
3412 * Operations defined by {n} and {l,r} are applied from left to right, and
3413 * the pattern that comes before has its delimiters defined either by () or
3414 * [] at its end or is taken from the beginning of the pattern (in
3415 * "a[bc]{2}", "{2}" is applied to "[bc]", and in "[01]abc{3}", the "{3}" is
3416 * applied to "[01]abc").
3417 */
3418
3419// If it has children, it is either a SEQ or an OR group, defined by the
3420// pattern_ field.
3421struct regex_node {
3422 // Considered to be repetition of left_bound != -1, pattern if
3423 // children_.empty(), otherwise "SEQ" or "OR", defined by the pattern_
3424 // field.
3425 std::string
3426 pattern_; // Either pattern, or "SEQ" or "OR" (if !children_.empty()).
3427 std::vector<regex_node> children_; // Children, when SEQ or OR.
3428 int left_bound_, right_bound_; // Left and right bounds of the repetition,
3429 // or -1 if not a repetition.
3430 double
3431 log_space_num_ways_; // Log space number of ways to match the pattern.
3432 std::optional<distinct_container<char>>
3433 distinct_; // Distinct generator for the pattern, for [chars].
3434
3435 // c or [chars].
3436 regex_node(const std::string &pattern)
3437 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3438 if (pattern.size() == 1) {
3439 log_space_num_ways_ = math::detail::LOG_ONE;
3440 return;
3441 }
3442 tgen_ensure_against_bug(pattern[0] == '[' and pattern.back() == ']',
3443 "str: invalid regex: expected character class");
3444 int size = pattern.size() - 2;
3445 log_space_num_ways_ = math::detail::log_space(size);
3446 distinct_ = distinct_container<char>(pattern.substr(1, size));
3447 }
3448 // SEQ or OR.
3449 regex_node(const std::string &pattern, std::vector<regex_node> &children)
3450 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3451 if (pattern == "SEQ") {
3452 // Multiply the number of ways.
3453 log_space_num_ways_ = math::detail::LOG_ONE;
3454 for (const auto &child : children)
3455 log_space_num_ways_ += child.log_space_num_ways_;
3456 } else if (pattern == "OR") {
3457 // Add the number of ways.
3458 log_space_num_ways_ = math::detail::LOG_ZERO;
3459 for (const auto &child : children)
3460 log_space_num_ways_ = math::detail::add_log_space(
3461 log_space_num_ways_, child.log_space_num_ways_);
3462 } else
3463 tgen_ensure_against_bug("str: invalid regex: expected SEQ or OR");
3464
3465 children_ = std::move(children);
3466 children.clear();
3467 }
3468 // REP.
3469 regex_node(int left_bound, int right_bound, regex_node &child)
3470 : pattern_("REP"), left_bound_(left_bound), right_bound_(right_bound) {
3471 log_space_num_ways_ = math::detail::LOG_ZERO;
3472 for (int i = left_bound; i <= right_bound; ++i)
3473 log_space_num_ways_ = math::detail::add_log_space(
3474 log_space_num_ways_, i * child.log_space_num_ways_);
3475
3476 children_.push_back(std::move(child));
3477 }
3478};
3479
3480// State of the regex parser.
3481struct regex_state {
3482 std::vector<regex_node> cur; // Current sequence of nodes.
3483 std::vector<regex_node> branches; // Branches of the current OR group.
3484};
3485
3486// Creates a SEQ node from the current state.
3487inline regex_node make_regex_seq(regex_state &st) {
3488 return regex_node("SEQ", st.cur);
3489}
3490
3491// Finishes current state.
3492inline regex_node finish_regex_state(regex_state &st) {
3493 // SEQ.
3494 if (st.branches.empty())
3495 return make_regex_seq(st);
3496
3497 // OR.
3498 st.branches.push_back(make_regex_seq(st));
3499 return regex_node("OR", st.branches);
3500}
3501
3502// Parses a regex pattern into a tree, computing the number of ways to match the
3503// pattern.
3504inline regex_node parse_regex(std::string regex) {
3505 std::string new_regex;
3506 for (char c : regex)
3507 if (c != ' ')
3508 new_regex += c;
3509 swap(regex, new_regex);
3510 regex_state cur;
3511 std::vector<regex_state> stack;
3512
3513 for (size_t i = 0; i < regex.size(); ++i) {
3514 char c = regex[i];
3515
3516 if (c == '(') {
3517 // Pushes the current state to the stack.
3518 stack.push_back(std::move(cur));
3519 cur = regex_state();
3520 } else if (c == ')') {
3521 // Finishes the current state, and adds it to the parent.
3522 regex_node node = finish_regex_state(cur);
3523
3524 tgen_ensure(!stack.empty(), "str: invalid regex: unmatched `)`");
3525 cur = std::move(stack.back());
3526 stack.pop_back();
3527
3528 cur.cur.push_back(std::move(node));
3529 } else if (c == '|') {
3530 // Starts a new OR group.
3531 regex_node node = make_regex_seq(cur);
3532 cur.branches.push_back(std::move(node));
3533 } else if (c == '[') {
3534 // Parses a character class.
3535 std::string chars;
3536
3537 for (++i; i < regex.size() and regex[i] != ']'; ++i) {
3538 if (i + 2 < regex.size() and regex[i + 1] == '-') {
3539 char a = regex[i], b = regex[i + 2];
3540 if (a > b)
3541 std::swap(a, b);
3542 for (char x = a; x <= b; ++x)
3543 chars += x;
3544 i += 2;
3545 } else
3546 chars += regex[i];
3547 }
3548
3549 tgen_ensure(i < regex.size() and regex[i] == ']',
3550 "str: invalid regex: unmatched `[`");
3551 cur.cur.emplace_back("[" + chars + "]");
3552 } else if (c == '{') {
3553 // Parses a repetition.
3554 ++i;
3555 int l = -1, r = -1;
3556
3557 while (i < regex.size() and
3558 isdigit(static_cast<unsigned char>(regex[i]))) {
3559 if (l == -1)
3560 l = 0;
3561 tgen_ensure(l <= static_cast<int>(1e8),
3562 "str: invalid regex: number too large inside `{}`");
3563 l = 10 * l + (regex[i] - '0');
3564 ++i;
3565 }
3566
3567 if (i < regex.size() and regex[i] == ',') {
3568 ++i;
3569 while (i < regex.size() and
3570 isdigit(static_cast<unsigned char>(regex[i]))) {
3571 if (r == -1)
3572 r = 0;
3574 r <= static_cast<int>(1e8),
3575 "str: invalid regex: number too large inside `{}`");
3576 r = 10 * r + (regex[i] - '0');
3577 ++i;
3578 }
3579 } else
3580 r = l;
3581
3582 tgen_ensure(i < regex.size() and regex[i] == '}',
3583 "str: invalid regex: unmatched `{`");
3584 tgen_ensure(l != -1 and r != -1,
3585 "str: invalid regex: missing number inside `{}`");
3586 tgen_ensure(l <= r,
3587 "str: invalid regex: invalid range inside `{}`");
3588
3589 // Creates a REP node from the previous node.
3590 tgen_ensure(!cur.cur.empty(),
3591 "str: invalid regex: expected expression before `{}`");
3592
3593 regex_node rep(l, r, cur.cur.back());
3594 cur.cur.pop_back();
3595 cur.cur.push_back(std::move(rep));
3596 } else {
3597 // Creates a char node.
3598 cur.cur.emplace_back(std::string(1, c));
3599 }
3600 }
3601
3602 tgen_ensure(stack.empty(), "str: invalid regex: unmatched `(`");
3603 return finish_regex_state(cur);
3604}
3605
3606// Generates a uniformly random string that matches the given regex.
3607inline void gen_regex(const regex_node &node, std::string &str) {
3608 // For [chars], generate a random character from the list.
3609 if (node.pattern_[0] == '[') {
3610 str += node.pattern_[1 + next<int>(0, node.pattern_.size() - 3)];
3611 return;
3612 }
3613
3614 // For REP, generate a random number of times to repeat the pattern.
3615 if (node.left_bound_ != -1) {
3616 // Generates a random value W from 0 to num_ways.
3617 // log(W) = log(random(0, 1) * num_ways)
3618 // = log(random(0, 1)) + log(num_ways).
3619 double log_rand = math::detail::log_space(next<double>(0, 1)) +
3620 node.log_space_num_ways_;
3621 double cur_prob = math::detail::LOG_ZERO;
3622 double child_num_ways = node.children_[0].log_space_num_ways_;
3623
3624 for (int i = node.left_bound_; i <= node.right_bound_; ++i) {
3625 cur_prob =
3626 math::detail::add_log_space(cur_prob, i * child_num_ways);
3627 if (log_rand <= cur_prob) {
3628 for (int j = 0; j < i; ++j)
3629 gen_regex(node.children_[0], str);
3630 return;
3631 }
3632 }
3633
3634 tgen_ensure_against_bug(false,
3635 "str: log_rand > cur_prob in REP gen_regex");
3636 }
3637
3638 // For SEQ, generate all children.
3639 if (!node.children_.empty() and node.pattern_ == "SEQ") {
3640 for (const regex_node &child : node.children_)
3641 gen_regex(child, str);
3642 return;
3643 }
3644
3645 // For OR, generate a random child.
3646 if (!node.children_.empty() and node.pattern_ == "OR") {
3647 // Generates a random value W from 0 to num_ways.
3648 // log(W) = log(random(0, 1) * num_ways)
3649 // = log(random(0, 1)) + log(num_ways).
3650 double log_rand = math::detail::log_space(next<double>(0, 1)) +
3651 node.log_space_num_ways_;
3652 double cur_prob = math::detail::LOG_ZERO;
3653
3654 for (const regex_node &child : node.children_) {
3655 cur_prob = math::detail::add_log_space(cur_prob,
3656 child.log_space_num_ways_);
3657 if (log_rand <= cur_prob) {
3658 gen_regex(child, str);
3659 return;
3660 }
3661 }
3662
3663 tgen_ensure_against_bug(false,
3664 "str: log_rand > cur_prob in OR gen_regex");
3665 }
3666
3667 // For char, generate the character.
3668 detail::tgen_ensure_against_bug(
3669 node.pattern_.size() == 1,
3670 "str: invalid regex: expected single character, but got `" +
3671 node.pattern_ + "`");
3672 str += node.pattern_[0];
3673}
3674
3675// Formats a regex string with given arguments.
3676template <typename... Args>
3677std::string regex_format(const std::string &s, Args &&...args) {
3678 if constexpr (sizeof...(Args) == 0) {
3679 return s;
3680 } else {
3681 int size = std::snprintf(nullptr, 0, s.c_str(), args...) + 1;
3682 std::string buf(size, '\0');
3683 std::snprintf(buf.data(), size, s.c_str(), args...);
3684 buf.pop_back(); // remove '\0'
3685 return buf;
3686 }
3687}
3688
3689} // namespace detail
3690
3691/*
3692 * String generator.
3693 */
3694
3695struct str : gen_base<str> {
3696 std::optional<list<char>> list_; // List of characters.
3697 std::optional<detail::regex_node>
3698 root_; // Root node of the regex tree for the whole string.
3699
3700 // Creates generator for strings of size 'size', with random characters in
3701 // [value_left, value_right].
3702 str(int size, char value_left = 'a', char value_right = 'z') {
3703 tgen_ensure(size > 0, "str: size must be positive");
3704 list_ = list<char>(size, value_left, value_right);
3705 }
3706
3707 // Creates generator for strings of size 'size', with random characters in
3708 // 'chars'.
3709 str(int size, std::set<char> chars) {
3710 tgen_ensure(size > 0, "str: size must be positive");
3711 list_ = list<char>(size, chars);
3712 }
3713
3714 // Creates generator for strings that match the given regex.
3715 template <typename... Args> str(const std::string &regex, Args &&...args) {
3716 tgen_ensure(regex.size() > 0, "str: regex must be non-empty");
3717
3718 root_ = detail::parse_regex(
3719 detail::regex_format(regex, std::forward<Args>(args)...));
3720 }
3721
3722 // Restricts strings for str[idx] = value.
3723 str &fix(int idx, char character) {
3724 tgen_ensure(!root_, "str: cannot add restriction for regex");
3725 list_->fix(idx, character);
3726 return *this;
3727 }
3728
3729 // Restricts strings for list[S] to be equal, for given subset S of indices.
3730 str &equal(std::set<int> indices) {
3731 tgen_ensure(!root_, "str: cannot add restriction for regex");
3732 list_->equal(indices);
3733 return *this;
3734 }
3735
3736 // Restricts strings for str[idx_1] = str[idx_2].
3737 str &equal(int idx_1, int idx_2) {
3738 tgen_ensure(!root_, "str: cannot add restriction for regex");
3739 list_->equal(idx_1, idx_2);
3740 return *this;
3741 }
3742
3743 // Restricts strings for str[left..right] to have all equal values.
3744 str &equal_range(int left, int right) {
3745 tgen_ensure(!root_, "str: cannot add restriction for regex");
3746 list_->equal_range(left, right);
3747 return *this;
3748 }
3749
3750 // Restricts strings for all equal chars.
3752 tgen_ensure(!root_, "str: cannot add restriction for regex");
3753 list_->all_equal();
3754 return *this;
3755 }
3756
3757 // Restricts strings for str[left..right] to be a palindrome.
3758 str &palindrome(int left, int right) {
3759 tgen_ensure(!root_, "str: cannot add restriction for regex");
3760 tgen_ensure(0 <= left and left <= right and right < list_->size_,
3761 "str: range indices must be valid");
3762 for (int i = left; i < right - (i - left); ++i)
3763 equal(i, right - (i - left));
3764 return *this;
3765 }
3766
3767 // Restricts strings for the entire string to be a palindrome.
3769 tgen_ensure(!root_, "str: cannot add restriction for regex");
3770 return palindrome(0, list_->size_ - 1);
3771 }
3772
3773 // Restricts strings for str[S] to be different (distinct), for given subset
3774 // S of indices.
3775 str &different(std::set<int> indices) {
3776 tgen_ensure(!root_, "str: cannot add restriction for regex");
3777 list_->different(indices);
3778 return *this;
3779 }
3780
3781 // Restricts strings for str[idx_1] != str[idx_2].
3782 str &different(int idx_1, int idx_2) {
3783 tgen_ensure(!root_, "str: cannot add restriction for regex");
3784 list_->different(idx_1, idx_2);
3785 return *this;
3786 }
3787
3788 // Restricts lists for list[left..right] to have all different chars.
3789 str &different_range(int left, int right) {
3790 tgen_ensure(!root_, "str: cannot add restriction for regex");
3791 list_->different_range(left, right);
3792 return *this;
3793 }
3794
3795 // Restricts strings for all chars to be different.
3797 tgen_ensure(!root_, "str: cannot add restriction for regex");
3798 list_->all_different();
3799 return *this;
3800 }
3801
3802 // str value.
3804 using tgen_is_sequential_tag = detail::is_sequential_tag;
3805
3806 using value_type = char;
3807 using std_type = std::string;
3808 std::string str_;
3809
3810 value(const std::string &str) : str_(str) {
3811 tgen_ensure(!str_.empty(), "str: value: cannot be empty");
3812 }
3813
3814 // Fetches size.
3815 int size() const { return str_.size(); }
3816
3817 // Fetches position idx.
3818 char &operator[](int idx) {
3819 tgen_ensure(0 <= idx and idx < size(),
3820 "str: value: index out of bounds");
3821 return str_[idx];
3822 }
3823 const char &operator[](int idx) const {
3824 tgen_ensure(0 <= idx and idx < size(),
3825 "str: value: index out of bounds");
3826 return str_[idx];
3827 }
3828
3829 // Sorts characters in non-decreasing order.
3830 // O(n log n).
3832 std::sort(str_.begin(), str_.end());
3833 return *this;
3834 }
3835
3836 // Reverses string.
3837 // O(n).
3839 std::reverse(str_.begin(), str_.end());
3840 return *this;
3841 }
3842
3843 // Lowercases all characters.
3844 // O(n).
3846 for (char &c : str_)
3847 c = std::tolower(c);
3848 return *this;
3849 }
3850
3851 // Uppercases all characters.
3852 // O(n).
3854 for (char &c : str_)
3855 c = std::toupper(c);
3856 return *this;
3857 }
3858
3859 // Concatenates two values.
3860 // Linear.
3861 value operator+(const value &rhs) const {
3862 return value(str_ + rhs.str_);
3863 }
3864
3865 // Shuffles string uniformly.
3866 // O(n).
3868 for (int i = 0; i < size(); ++i)
3869 std::swap(str_[i], str_[next(0, size() - 1)]);
3870 return *this;
3871 }
3872
3873 // Returns a random character uniformly.
3874 // O(1).
3875 char pick() const { return str_[next<int>(0, size() - 1)]; }
3876
3877 // Returns str_[i] with probability proportional to distribution[i].
3878 // O(1).
3879 template <typename Dist>
3880 char pick_by_distribution(const std::vector<Dist> &distribution) const {
3881 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
3882 "value and distribution must have the same size");
3883 return str_[next_by_distribution(distribution)];
3884 }
3885 template <typename Dist>
3886 char pick_by_distribution(
3887 const std::initializer_list<Dist> &distribution) const {
3888 return pick_by_distribution(std::vector<Dist>(distribution));
3889 }
3890
3891 // Chooses k characters uniformly, as in a subsequence of size k.
3892 // O(n).
3893 value choose(int k) const {
3894 tgen_ensure(0 < k and k <= size(),
3895 "number of elements to choose must be valid");
3896 std::string new_str;
3897 int need = k;
3898 for (int i = 0; need > 0; ++i) {
3899 int left = size() - i;
3900 if (next(1, left) <= need) {
3901 new_str.push_back(str_[i]);
3902 need--;
3903 }
3904 }
3905 return value(new_str);
3906 }
3907
3908 // Prints to std::ostream.
3909 friend std::ostream &operator<<(std::ostream &out, const value &val) {
3910 return out << val.str_;
3911 }
3912
3913 // Gets a std::string representing the value.
3914 std::string to_std() const { return std_type(str_); }
3915 };
3916
3917 // Generates str value.
3918 // If created from restrictions: O(n log n).
3919 // If created from regex: expected linear.
3920 value gen() const {
3921 if (root_) {
3922 // Regex.
3923 std::string ret_str;
3924 gen_regex(*root_, ret_str);
3925 return value(ret_str);
3926 } else {
3927 // List.
3928 std::vector<char> vec = list_->gen().to_std();
3929 return value(std::string(vec.begin(), vec.end()));
3930 }
3931 }
3932};
3933
3934/************
3935 * *
3936 * PAIR *
3937 * *
3938 ************/
3939
3940namespace detail {
3941
3942// Generates pair first == second.
3943// O(1).
3944template <typename T> std::pair<T, T> gen_eq(T L1, T R1, T L2, T R2) {
3945 T L = std::max(L1, L2);
3946 T R = std::min(R1, R2);
3947
3948 tgen_ensure(L <= R, "pair: no valid values to generate");
3949 T x = next<T>(L, R);
3950 return {x, x};
3951}
3952
3953// Returns {R1-L1+1, R2-L2+1}.
3954template <typename T>
3955std::pair<u128, u128> get_n_and_m(T L1, T R1, T L2, T R2) {
3956 u128 n = static_cast<i128>(R1) - L1 + 1;
3957 u128 m = static_cast<i128>(R2) - L2 + 1;
3958 return {n, m};
3959}
3960
3961// Returns first + first+1 + ... + last,
3962// num_terms terms. Avoids overflow.
3963static u128 pos_arith_sum(u128 first, u128 last, u128 num_terms) {
3964 u128 x = first + last, y = num_terms;
3965
3966 // x * y / 2, avoiding overflow.
3967 if (x % 2 == 0)
3968 x /= 2;
3969 else
3970 y /= 2;
3971
3972 return x * y;
3973}
3974
3975// Generates pair first != second.
3976// O(1) expected.
3977template <typename T> std::pair<T, T> gen_neq(T L1, T R1, T L2, T R2) {
3978 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
3979
3980 T L_intersect = std::max(L1, L2);
3981 T R_intersect = std::min(R1, R2);
3982 u128 inter = static_cast<i128>(R_intersect) - L_intersect + 1;
3983
3984 u128 total = n * m - inter;
3985 tgen_ensure(total > 0, "pair: no valid values to generate");
3986
3987 // Runs O(1) expected times in the worst case.
3988 T a, b;
3989 do {
3990 a = next<T>(L1, R1);
3991 b = next<T>(L2, R2);
3992 } while (a == b);
3993
3994 return {a, b};
3995}
3996
3997// For lt, splits 'second' into two regions:
3998// 1) second <= R1 -> number of 'first' is (second - L1)
3999// 2) second > R1 -> number of 'first' is (R1 - L1 + 1)
4000// Returns {count_region1, count_region2}.
4001// O(1).
4002template <typename T>
4003std::pair<u128, u128> count_lt_regions(T L1, T R1, T L2, T R2) {
4004 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4005
4006 // 'second' must be >= L1 + 1.
4007 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);
4008 i128 R_second = R2;
4009
4010 // Split point for 'second'.
4011 i128 split = std::min<i128>(R_second, R1);
4012
4013 // Region 1: b in [L_second, split].
4014 u128 len1 = std::max<i128>(0, split - L_second + 1);
4015
4016 u128 count_region1 = 0;
4017 if (len1 > 0) {
4018 // For b in [L_second, split], there are (b - L1) ways.
4019 i128 first = L_second - L1;
4020 i128 last = split - L1;
4021
4022 // Arithmetic series first + (first + 1) + ... + last, len1 terms.
4023 count_region1 = pos_arith_sum(first, last, len1);
4024 }
4025
4026 // Region 2: b > R1.
4027 // For b in [R1+1, R_second], there are 'n' ways.
4028 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);
4029
4030 u128 len2 = std::max<i128>(0, R_second - L_second_region2 + 1);
4031 u128 count_region2 = len2 * n;
4032
4033 return {count_region1, count_region2};
4034}
4035
4036// Generates pair first < second.
4037// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4038template <typename T> std::pair<T, T> gen_lt(T L1, T R1, T L2, T R2) {
4039 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4040
4041 // 'second' needs to be at least L1 + 1 to have a valid value for
4042 // 'first'.
4043 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);
4044 i128 R_second = R2;
4045
4046 // Splits 'second' into two regions:
4047 // 1) b <= R1 -> number of 'first' is (b - L1);
4048 // 2) b > R1 -> number of 'first' is (R1 - L1 + 1).
4049 i128 split = std::min<i128>(R_second, R1);
4050
4051 auto [count_region1, count_region2] = count_lt_regions(L1, R1, L2, R2);
4052 u128 total = count_region1 + count_region2;
4053 tgen_ensure(total > 0, "pair: no valid values to generate");
4054
4055 u128 k = detail::next128(total);
4056 if (k < count_region1) {
4057 // Region 1: invert arithmetic series.
4058
4059 // For b in [L_second, split].
4060 u128 len1 = std::max<i128>(0, split - L_second + 1);
4061
4062 // We consider b in [L_second, L_second + d].
4063 // Each b contributes (b - L1) = base + (b - L_second).
4064 // So we sum: base + (base+1) + ... + (base+d)
4065 // d in [0, len1).
4066
4067 i128 base = L_second - L1;
4068 i128 lo = 0, hi = static_cast<i128>(len1) - 1;
4069
4070 while (lo < hi) {
4071 i128 mid = lo + (hi - lo) / 2;
4072
4073 if (pos_arith_sum(base, base + mid, mid + 1) <= k)
4074 lo = mid + 1;
4075 else
4076 hi = mid;
4077 }
4078 i128 d = lo;
4079
4080 // Subtracts prefix sum with d-1 terms from k.
4081 if (d > 0)
4082 k -= pos_arith_sum(base, base + d - 1, d);
4083
4084 return {L1 + static_cast<T>(k), L_second + d};
4085 } else {
4086 // Region 2: uniform block of size n.
4087 k -= count_region1;
4088
4089 // For b in [R1+1, R_second], there are 'n' ways.
4090 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);
4091
4092 return {L1 + static_cast<T>(k % n),
4093 L_second_region2 + static_cast<T>(k / n)};
4094 }
4095}
4096
4097// Generates pair first > second.
4098// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4099template <typename T> std::pair<T, T> gen_gt(T L1, T R1, T L2, T R2) {
4100 auto [first, second] = gen_lt(L2, R2, L1, R1);
4101 return {second, first};
4102}
4103
4104// Generates pair first <= second.
4105// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4106template <typename T> std::pair<T, T> gen_leq(T L1, T R1, T L2, T R2) {
4107 // Counts how many pairs are there with first = second.
4108 i128 L_intersect = std::max(L1, L2);
4109 i128 R_intersect = std::min(R1, R2);
4110 u128 eq_count = std::max<i128>(0, R_intersect - L_intersect + 1);
4111
4112 // Counts how many pairs are there with first < second.
4113 auto [lt_region1, lt_region2] = count_lt_regions(L1, R1, L2, R2);
4114 u128 lt_count = lt_region1 + lt_region2;
4115
4116 u128 total = eq_count + lt_count;
4117 tgen_ensure(total > 0, "pair: no valid values to generate");
4118
4119 if (detail::next128(total) < eq_count)
4120 return gen_eq(L1, R1, L2, R2);
4121 return gen_lt(L1, R1, L2, R2);
4122}
4123
4124// Generates pair first >= second.
4125// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4126template <typename T> std::pair<T, T> gen_geq(T L1, T R1, T L2, T R2) {
4127 auto [first, second] = gen_leq(L2, R2, L1, R1);
4128 return {second, first};
4129}
4130
4131}; // namespace detail
4132
4133/*
4134 * Pair generator.
4135 *
4136 * Pairs of integral types.
4137 */
4138
4139template <typename T> struct pair : gen_base<pair<T>> {
4140 std::pair<T, T> first_, second_; // Range of first and second values.
4141 // Type of restriction.
4142 enum class restriction_type { eq, neq, lt, gt, leq, geq, unspecified };
4143 restriction_type type_ = restriction_type::unspecified;
4144
4145 // Creates a pair with random values in [first_l, first_r] and [second_l,
4146 // second_r].
4147 pair(T first_left, T first_right, T second_left, T second_right)
4148 : first_(first_left, first_right), second_(second_left, second_right) {
4149 tgen_ensure(first_left <= first_right,
4150 "pair: first range must be valid");
4151 tgen_ensure(second_left <= second_right,
4152 "pair: second range must be valid");
4153 }
4154
4155 // Creates a pair with random values in [both_l, both_r].
4156 pair(T both_left, T both_right)
4157 : pair(both_left, both_right, both_left, both_right) {}
4158
4159 // Restricts pair for first = second.
4161 type_ = restriction_type::eq;
4162 return *this;
4163 }
4164
4165 // Restricts pair for first != second.
4167 type_ = restriction_type::neq;
4168 return *this;
4169 }
4170
4171 // Restricts pair for first < second.
4173 type_ = restriction_type::lt;
4174 return *this;
4175 }
4176
4177 // Restricts pair for first > second.
4179 type_ = restriction_type::gt;
4180 return *this;
4181 }
4182
4183 // Restricts pair for first <= second.
4185 type_ = restriction_type::leq;
4186 return *this;
4187 }
4188
4189 // Restricts pair for first >= second.
4191 type_ = restriction_type::geq;
4192 return *this;
4193 }
4194
4195 // Pair value.
4197 using value_type = T;
4198 using std_type = std::pair<T, T>;
4199
4200 std::pair<T, T> pair_;
4201 char sep_;
4202
4203 value(const std::pair<T, T> &pair) : pair_(pair), sep_(' ') {}
4204 value(const T &first, const T &second)
4205 : pair_(first, second), sep_(' ') {}
4206
4207 T first() const { return pair_.first; }
4208 T second() const { return pair_.second; }
4209
4210 // Sets the separator for the pair, for printing.
4211 value &separator(char sep) {
4212 sep_ = sep;
4213 return *this;
4214 }
4215
4216 // Prints to std::ostream, separated by sep_.
4217 friend std::ostream &operator<<(std::ostream &out, const value &val) {
4218 return out << val.pair_.first << val.sep_ << val.pair_.second;
4219 }
4220
4221 // Gets a std::pair representing the value.
4222 auto to_std() const {
4223 if constexpr (!detail::is_generator_value<T>::value) {
4224 return pair_;
4225 } else {
4226 std::pair<typename T::std_type, typename T::std_type> pair(
4227 pair_.first.to_std(), pair_.second.to_std());
4228 return pair;
4229 }
4230 }
4231 };
4232
4233 // Generates a random pair.
4234 // O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4235 value gen() const {
4236 T L1 = first_.first, R1 = first_.second;
4237 T L2 = second_.first, R2 = second_.second;
4238
4239 switch (type_) {
4240 case restriction_type::unspecified:
4241 return {next<T>(L1, R1), next<T>(L2, R2)};
4242 case restriction_type::eq:
4243 return detail::gen_eq<T>(L1, R1, L2, R2);
4244 case restriction_type::neq:
4245 return detail::gen_neq<T>(L1, R1, L2, R2);
4246 case restriction_type::lt:
4247 return detail::gen_lt<T>(L1, R1, L2, R2);
4248 case restriction_type::gt:
4249 return detail::gen_gt<T>(L1, R1, L2, R2);
4250 case restriction_type::leq:
4251 return detail::gen_leq<T>(L1, R1, L2, R2);
4252 case restriction_type::geq:
4253 return detail::gen_geq<T>(L1, R1, L2, R2);
4254 }
4255 throw detail::error("pair: unknown restriction type");
4256 }
4257};
4258
4259/************
4260 * *
4261 * TREE *
4262 * *
4263 ************/
4264
4265namespace detail {
4266
4267// Generates edges from Prufer sequence.
4268// O(n).
4269inline std::vector<std::pair<int, int>> edges_from_prufer(std::vector<int> p) {
4270 int n = p.size() + 2;
4271
4272 // Degrees.
4273 std::vector<int> d(n, 1);
4274 for (int i : p)
4275 d[i]++;
4276
4277 // Adds last vertex.
4278 p.push_back(n - 1);
4279
4280 // Finds first vertex with degree 1.
4281 int idx, u;
4282 idx = u = find(d.begin(), d.end(), 1) - d.begin();
4283
4284 // Generates edges.
4285 std::vector<std::pair<int, int>> edges;
4286 for (int v : p) {
4287 edges.emplace_back(u, v);
4288 if (--d[v] == 1 and v < idx)
4289 u = v;
4290 else
4291 idx = u = find(d.begin() + idx + 1, d.end(), 1) - d.begin();
4292 }
4293 return edges;
4294}
4295
4296// Disjoint set union (union-find) for connectivity queries.
4297struct dsu {
4298 std::vector<int> parent_;
4299 std::vector<unsigned char> rank_;
4300
4301 // Creates a dsu with `n` elements, indexed from 0 to n-1.
4302 // Initially every element is in its own set.
4303 // O(n).
4304 dsu(int n) : parent_(n), rank_(n, 0) {
4305 for (int i = 0; i < n; ++i)
4306 parent_[i] = i;
4307 }
4308
4309 // Adds new elements to the dsu, each in their own new set.
4310 // O(k) amortized.
4311 void add_elements(int k) {
4312 for (int i = 0; i < k; ++i) {
4313 int new_id = parent_.size();
4314 parent_.push_back(new_id);
4315 rank_.push_back(0);
4316 }
4317 }
4318
4319 // Finds representative of set containing i.
4320 // O(alpha(n)) amortized, O(log n) worst case.
4321 int find(int i) {
4322 return parent_[i] == i ? i : parent_[i] = find(parent_[i]);
4323 }
4324
4325 // Merges components of `a` and `b`. Returns if the sets were united, and
4326 // false if a and b were in the same set.
4327 // O(alpha(n)) amortized, O(log n) worst case.
4328 bool unite(int a, int b) {
4329 a = find(a);
4330 b = find(b);
4331 if (a == b)
4332 return false;
4333 if (rank_[a] > rank_[b])
4334 std::swap(a, b);
4335 parent_[a] = b;
4336 if (rank_[a] == rank_[b])
4337 ++rank_[b];
4338 return true;
4339 }
4340};
4341
4342} // namespace detail
4343
4344// Forward declaration of wgraph.
4345template <typename VWeight, typename EWeight> struct wgraph;
4346
4347/*
4348 * Tree generator.
4349 *
4350 * Unrooted trees with `n` vertices, indexed from 0 to n-1.
4351 * These are unrooted undirected labeled trees, that is, isomorphism is not
4352 * taken into account. VWeight is the type of vertex weights, and EWeight is
4353 * the type of edge weights. Generator does not generate weights. The weights
4354 * are to be set in the wtree::value.
4355 */
4356
4357template <typename VWeight, typename EWeight>
4358struct wtree : gen_base<wtree<VWeight, EWeight>> {
4359 int n_; // Number of vertices.
4360 std::set<std::pair<int, int>> edges_; // Edges that were set.
4361
4362 // Creates tree generator with `n` vertices.
4363 // O(1).
4364 wtree(int n) : n_(n) {
4365 tgen_ensure(n > 0, "wtree: number of vertices must be positive");
4366 }
4367
4368 // Adds edge between u and v (this edge must be generated).
4369 // O(log n).
4370 wtree &add_edge(int u, int v) {
4371 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,
4372 "wtree: vertices must be indexed in [0, n)");
4373 tgen_ensure(u != v, "wtree: cannot add self loop to tree");
4374
4375 if (u > v)
4376 std::swap(u, v);
4377 edges_.emplace(u, v);
4378 return *this;
4379 }
4380
4381 // Tree value.
4382 //
4383 // Edges are stored in both directions in adjacency list, but only u < v in
4384 // edge list.
4386 using std_type = std::pair<int, std::vector<std::set<int>>>;
4387
4388 int n_; // Number of vertices.
4389 std::vector<std::set<int>> adj_; // Adjacency list.
4390 std::vector<std::pair<int, int>> edges_; // Edge list.
4391 bool add_1_; // If should add 1 for printing vertex ids.
4392 bool print_n_; // If should print n.
4393 std::optional<int> print_parents_; // If should print in parent style
4394 // (stores the root).
4395 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.
4396 std::optional<std::vector<EWeight>>
4397 edge_weights_; // Edge weights (in same order as edges_).
4398 detail::dsu dsu_; // Connectivity of current edges (for cycle checks).
4399
4400 // Creates value from adjacency list.
4401 // O(n).
4402 value(const std::vector<std::set<int>> &adj)
4403 : n_(static_cast<int>(adj.size())), adj_(adj), add_1_(false),
4404 print_n_(false), dsu_(n_) {
4405 for (int u = 0; u < n_; ++u)
4406 for (auto v : adj[u]) {
4408 0 <= v and v < n_,
4409 "wtree: value: vertices must be indexed in [0, n)");
4410 // Symmetric adjacency: count each undirected edge once.
4411 if (u < v) {
4412 edges_.emplace_back(u, v);
4414 dsu_.unite(u, v),
4415 "wtree: value: initial graph must form a tree");
4416 }
4417 }
4418 }
4419
4420 // Creates value from `n` and edge list.
4421 // O(n).
4422 value(int n, const std::vector<std::pair<int, int>> &edges)
4423 : n_(n), adj_(n), add_1_(false), print_n_(false), dsu_(n) {
4424 edges_.reserve(edges.size());
4425 for (auto [u, v] : edges) {
4426 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n,
4427 "wtree: value: vertices must be indexed in [0, n)");
4428 tgen_ensure(dsu_.unite(u, v),
4429 "wtree: value: initial graph must form a tree");
4430 if (u > v)
4431 std::swap(u, v);
4432 edges_.emplace_back(u, v);
4433 adj_[u].insert(v);
4434 adj_[v].insert(u);
4435 }
4436 }
4437 value(int n, const std::set<std::pair<int, int>> &edges)
4438 : value(n, std::vector<std::pair<int, int>>(edges.begin(),
4439 edges.end())) {}
4440 value(int n, const std::initializer_list<std::pair<int, int>> &edges)
4441 : value(n, std::vector<std::pair<int, int>>(edges)) {}
4442
4443 // Creates tree from graph via Kruskal-like random spanning tree.
4444 // Implemented after wgraph definition.
4445 // O(n + m alpha(n)).
4446 value(const typename wgraph<VWeight, EWeight>::value &g);
4447
4448 // Weight type conversion.
4449 // O(n).
4450 template <typename NewVWeight, typename NewEWeight>
4451 typename wtree<NewVWeight, NewEWeight>::value
4452 convert_weight_types() const {
4453 tgen_ensure(!vertex_weights_.has_value() and
4454 !edge_weights_.has_value(),
4455 "wtree: value: cannot convert weight type after "
4456 "assigning weights");
4457
4458 typename wtree<NewVWeight, NewEWeight>::value new_tree(adj_);
4459 new_tree.add_1_ = add_1_;
4460 new_tree.print_n_ = print_n_;
4461 new_tree.print_parents_ = print_parents_;
4462 return new_tree;
4463 }
4464
4465 // Fetches number of vertices.
4466 int n() const { return n_; }
4467
4468 // Fetches a const ref. to adjacency list.
4469 const std::vector<std::set<int>> &adj() const { return adj_; }
4470
4471 // Fetches a const ref. to edge list.
4472 const std::vector<std::pair<int, int>> &edges() const { return edges_; }
4473
4474 // Fetches a const ref. to vertex weights.
4476 return vertex_weights_;
4477 }
4478
4479 // Fetches a const ref. to edge weights.
4481 return edge_weights_;
4482 }
4483
4484 // Sets vertex weights.
4485 // O(n).
4486 template <typename NewVWeight = VWeight>
4487 typename wtree<NewVWeight, EWeight>::value set_vertex_weights(
4488 const std::vector<NewVWeight> &vertex_weights) const {
4489 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),
4490 "wtree: value: must give `n` vertex weights");
4491
4492 auto new_tree = convert_weight_types<NewVWeight, EWeight>();
4493 new_tree.vertex_weights_ = vertex_weights;
4494 return new_tree;
4495 }
4496
4497 // Sets edge weights.
4498 // O(n).
4499 template <typename NewEWeight = EWeight>
4500 typename wtree<VWeight, NewEWeight>::value
4501 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {
4503 edge_weights.size() == edges().size(),
4504 "wtree: value: must give `edges().size()` edge weights");
4505
4506 auto new_tree = convert_weight_types<VWeight, NewEWeight>();
4507 new_tree.edge_weights_ = edge_weights;
4508 return new_tree;
4509 }
4510
4511 // Enables edge-weighted mode before adding weighted edges
4512 // incrementally. The tree must have no edges yet. O(1).
4514 tgen_ensure(edges().size() == 0,
4515 "wtree: value: edge_weighted requires a tree with no "
4516 "edges");
4517 tgen_ensure(!edge_weights_.has_value(),
4518 "wtree: value: tree is already edge-weighted");
4519
4520 edge_weights_ = std::vector<EWeight>();
4521 return *this;
4522 }
4523
4524 // Adds 1 to vertex ids, for printing.
4525 // O(1).
4527 add_1_ = true;
4528 return *this;
4529 }
4530
4531 // Prints `n` on a new line before printing the tree.
4532 // O(1).
4534 print_n_ = true;
4535 return *this;
4536 }
4537
4538 // Prints the tree in parent style.
4539 // If root = -1, the root is considered to be 0, and its parent is not
4540 // printed. Otherwise, prints the parent of the root as -1. If root = n,
4541 // randomizes the root. O(1).
4542 value &print_parents(int root = -1) {
4543 tgen_ensure(root == -1 or (0 <= root and root < n()) or root == n(),
4544 "wtree: value: root must be -1, `n`, or in [0, n)");
4545 print_parents_ = root;
4546 return *this;
4547 }
4548
4549 // Shuffles the tree's vertex labels (except those in `indices`,
4550 // which keep their current label) and edge order. The change is
4551 // applied eagerly to the underlying adjacency list, edge list,
4552 // vertex weights and edge weights.
4553 // O(n).
4554 value &shuffle_except(std::set<int> indices) {
4555 // Builds the relabeling: for each vertex `i`, `new_label[i]` is
4556 // its new id. Vertices in `indices` keep their label; the others
4557 // are permuted among themselves.
4558 std::vector<int> new_label(n());
4559 std::vector<int> shuffled;
4560 for (int i = 0; i < n(); ++i) {
4561 if (indices.count(i))
4562 new_label[i] = i;
4563 else
4564 shuffled.push_back(i);
4565 }
4566 std::vector<int> targets = shuffled;
4567 tgen::shuffle(targets.begin(), targets.end());
4568 for (size_t k = 0; k < shuffled.size(); ++k)
4569 new_label[shuffled[k]] = targets[k];
4570
4571 // Rewrites adjacency list with new labels.
4572 std::vector<std::set<int>> new_adj(n());
4573 for (int u = 0; u < n(); ++u)
4574 for (int v : adj_[u])
4575 new_adj[new_label[u]].insert(new_label[v]);
4576 adj_ = std::move(new_adj);
4577
4578 // Rewrites edges with new labels (canonical undirected order).
4579 for (auto &[u, v] : edges_) {
4580 u = new_label[u];
4581 v = new_label[v];
4582 if (u > v)
4583 std::swap(u, v);
4584 }
4585
4586 // Permutes vertex weights to match the new labels.
4587 if (vertex_weights_.has_value()) {
4588 std::vector<VWeight> new_vw(n());
4589 for (int i = 0; i < n(); ++i)
4590 new_vw[new_label[i]] = (*vertex_weights_)[i];
4591 vertex_weights_ = std::move(new_vw);
4592 }
4593
4594 // Rebuilds the dsu so future `add_edge` calls see the new labels.
4595 dsu_ = detail::dsu(n());
4596 for (auto [u, v] : edges_)
4597 dsu_.unite(u, v);
4598
4599 // Shuffles edge order, keeping edge weights aligned.
4600
4601 std::vector<int> perm(edges_.size());
4602 std::iota(perm.begin(), perm.end(), 0);
4603 tgen::shuffle(perm.begin(), perm.end());
4604
4605 std::vector<std::pair<int, int>> new_edges;
4606 std::optional<std::vector<EWeight>> new_ew;
4607 if (edge_weights_.has_value())
4608 new_ew = std::vector<EWeight>();
4609 for (int i : perm) {
4610 new_edges.push_back(edges_[i]);
4611 if (new_ew.has_value())
4612 new_ew->push_back((*edge_weights_)[i]);
4613 }
4614 edges_ = new_edges;
4615 if (new_ew.has_value())
4616 edge_weights_ = new_ew;
4617
4618 return *this;
4619 }
4620
4621 // Shuffles the tree's vertices and edge order.
4622 // O(n).
4623 value &shuffle() { return shuffle_except({}); }
4624
4625 // Adds edge (u, v).
4626 // O(log n) amortized.
4627 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {
4628 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),
4629 "wtree: value: vertex ids must be valid");
4630
4631 if (u > v)
4632 std::swap(u, v);
4633
4634 if (adj_[u].count(v))
4635 return *this;
4636
4637 adj_[u].insert(v);
4638 adj_[v].insert(u);
4639 edges_.emplace_back(u, v);
4640 tgen_ensure(dsu_.unite(u, v),
4641 "wtree: value: added edge must not create a cycle");
4642
4643 if (w.has_value()) {
4644 tgen_ensure(edge_weights().has_value(),
4645 "wtree: value: cannot add weighted edge to "
4646 "edge-unweighted tree");
4647
4648 edge_weights_->push_back(*w);
4649 } else
4650 tgen_ensure(!edge_weights().has_value(),
4651 "wtree: value: cannot add unweighted edge to "
4652 "edge-weighted tree");
4653
4654 return *this;
4655 }
4656
4657 // Links tree with another `rhs`, adding the edge between u (in left
4658 // tree) and v (in right tree). Ids for added vertices are updated
4659 // accordingly.
4660 // O(rhs.n + rhs.m * log n) amortized.
4661 value &link(const value &rhs, int new_u, int new_v,
4662 std::optional<EWeight> new_w = std::nullopt) {
4663 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and
4664 new_v < rhs.n(),
4665 "wtree: value: vertex ids must be valid");
4666
4667 // Edges from right-hand side.
4668 int shift = n();
4669 add_vertices(rhs.n(), rhs.vertex_weights());
4670 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {
4671 auto [u, v] = rhs.edges()[i];
4672 add_edge(shift + u, shift + v,
4673 rhs.edge_weights().has_value()
4674 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4675 : std::nullopt);
4676 }
4677
4678 // New edge.
4679 add_edge(new_u, shift + new_v, new_w);
4680
4681 return *this;
4682 }
4683
4684 // Glues the tree with another `rhs` such that index_pairs[i].first is
4685 // considered to be the same as index_pairs[i].second. Ids for added
4686 // vertices are updated accordingly.
4687 // O(rhs.n + rhs.m * log n) amortized.
4688 value &glue(const value &rhs,
4689 std::set<std::pair<int, int>> index_pairs) {
4690 // Checks validity of indices.
4691 std::set<int> idx_left, idx_right;
4692 std::vector<int> right_id_to_left(rhs.n(), -1);
4693 for (auto [l, r] : index_pairs) {
4695 0 <= l and l < n() and 0 <= r and r < rhs.n(),
4696 "wtree: value: vertex indices to glue must be valid");
4697 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,
4698 "wtree: value: must not have repeated indices "
4699 "on the same side to glue");
4700
4701 idx_left.insert(l);
4702 idx_right.insert(r);
4703 right_id_to_left[r] = l;
4704 }
4705
4706 // Computes new ids of right vertices.
4707 std::vector<int> new_right_id(rhs.n(), -1);
4708 int intersection_lt = 0;
4709 std::optional<std::vector<VWeight>> rhs_vertex_weights;
4710 for (int i = 0; i < rhs.n(); ++i) {
4711 if (right_id_to_left[i] != -1) {
4712 // Is in intersection.
4713 ++intersection_lt;
4714 new_right_id[i] = right_id_to_left[i];
4715 } else {
4716 // New id.
4717 new_right_id[i] = n() + i - intersection_lt;
4718 if (rhs.vertex_weights().has_value()) {
4719 if (!rhs_vertex_weights.has_value())
4720 rhs_vertex_weights = std::vector<VWeight>();
4721 rhs_vertex_weights->push_back(
4722 (*rhs.vertex_weights())[i]);
4723 }
4724 }
4725 }
4726
4727 // Adds new vertices and edges.
4728 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
4729 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {
4730 auto [u, v] = rhs.edges()[i];
4731 add_edge(new_right_id[u], new_right_id[v],
4732 rhs.edge_weights().has_value()
4733 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4734 : std::nullopt);
4735 }
4736
4737 return *this;
4738 }
4739 value &glue(const value &rhs,
4740 std::initializer_list<std::pair<int, int>> il) {
4741 return glue(rhs, std::set<std::pair<int, int>>(il));
4742 }
4743
4744 // Glues the tree with another `rhs` at `indices`. That is, idx in
4745 // `indices` are considered to be the same vertex. Ids for added
4746 // vertices are updated accordingly.
4747 // O(rhs.n).
4748 value &glue(const value &rhs, std::set<int> indices) {
4749 std::set<std::pair<int, int>> index_pairs;
4750 for (auto i : indices)
4751 index_pairs.emplace(i, i);
4752 return glue(rhs, index_pairs);
4753 }
4754 value &glue(const value &rhs, const std::initializer_list<int> &il) {
4755 return glue(rhs, std::set<int>(il));
4756 }
4757
4758 // Prints to std::ostream.
4759 // O(n).
4760 friend std::ostream &operator<<(std::ostream &out, const value &val) {
4761 if (val.print_n_)
4762 out << val.n() << '\n';
4763
4764 // Prints vertex weights.
4765 if (val.vertex_weights()) {
4766 for (int i = 0; i < val.n(); ++i) {
4767 if (i > 0)
4768 out << " ";
4769 out << (*val.vertex_weights())[i];
4770 }
4771 out << '\n';
4772 }
4773
4774 tgen_ensure(static_cast<int>(val.edges().size()) == val.n() - 1,
4775 "wtree: value: invalid tree to print (number of edges "
4776 "must be `n` - 1)");
4777
4778 // Prints in parent style.
4779 if (val.print_parents_.has_value()) {
4780 tgen_ensure(!val.edge_weights().has_value(),
4781 "wtree: value: cannot print parent style if edges "
4782 "are weighted");
4783
4784 int root = *val.print_parents_;
4785 bool skip_parent_0 = root == -1;
4786 if (root == -1)
4787 root = 0;
4788 if (root == val.n())
4789 root = next(0, val.n() - 1);
4790
4791 std::vector<int> parent(val.n(), -1);
4792
4793 std::queue<int> q;
4794 std::vector<int> vis(val.n(), false);
4795 q.push(root);
4796 vis[root] = true;
4797
4798 while (q.size()) {
4799 int u = q.front();
4800 q.pop();
4801 for (int v : val.adj()[u])
4802 if (!vis[v]) {
4803 vis[v] = true;
4804 q.push(v);
4805 parent[v] = u;
4806 }
4807 }
4808
4809 if (skip_parent_0) {
4810 for (int i = 1; i < val.n(); ++i) {
4812 parent[i] < i,
4813 "wtree: value: parent of i must be less than i for "
4814 "printing in parent style if root is -1");
4815
4816 if (i > 1)
4817 out << " ";
4818 out << parent[i] + val.add_1_;
4819 }
4820 } else {
4821 for (int i = 0; i < val.n(); ++i) {
4822 if (i > 0)
4823 out << " ";
4824 out << (parent[i] == -1 ? -1 : parent[i]) + val.add_1_;
4825 }
4826 }
4827
4828 out << '\n';
4829 return out;
4830 }
4831
4832 // Prints edges.
4833 for (int i = 0; i < static_cast<int>(val.edges().size()); ++i) {
4834 auto [u, v] = val.edges()[i];
4835 out << (u + val.add_1_) << " " << (v + val.add_1_);
4836
4837 // Edge weight.
4838 if (val.edge_weights().has_value())
4839 out << " " << (*val.edge_weights())[i];
4840
4841 out << '\n';
4842 }
4843
4844 return out;
4845 }
4846
4847 // Gets a std::pair<n, adj> representing the value.
4848 std::pair<int, std::vector<std::set<int>>> to_std() const {
4849 return std_type(n_, adj_);
4850 }
4851
4852 private:
4853 // Adds `k` vertices to the tree (labeled n, n+1, ...n+k-1). Updates
4854 // `n` accordingly. This makes the tree invalid (not a tree anymore).
4855 // O(k) amortized.
4856 value &add_vertices(int k, std::optional<std::vector<VWeight>>
4857 new_vertex_weights = std::nullopt) {
4858 n_ += k;
4859 adj_.resize(n());
4860 if (new_vertex_weights.has_value()) {
4861 tgen_ensure(vertex_weights().has_value(),
4862 "wtree: value: cannot add weighted vertices to "
4863 "vertex-unweighted tree");
4865 static_cast<int>(new_vertex_weights->size()) == k,
4866 "wtree: value: number of vertex weights must be equal "
4867 "to number of added vertices");
4868
4869 vertex_weights_->insert(vertex_weights_->end(),
4870 new_vertex_weights->begin(),
4871 new_vertex_weights->end());
4872 } else
4873 tgen_ensure(!vertex_weights().has_value(),
4874 "wtree: value: cannot add unweighted vertices to "
4875 "vertex-weighted tree");
4876
4877 dsu_.add_elements(k);
4878
4879 return *this;
4880 }
4881 };
4882
4883 // Generates tree value.
4884 // O(n).
4885 value gen() const {
4886 // Constructs adjacency list.
4887 std::vector<std::vector<int>> adj(n_);
4888 for (auto [u, v] : edges_) {
4889 adj[u].push_back(v);
4890 adj[v].push_back(u);
4891 }
4892
4893 std::vector<int> comp_size;
4894 std::vector<std::vector<int>> component_ids;
4895 std::vector<bool> vis(n_, false);
4896 std::queue<int> q;
4897
4898 for (int i = 0; i < n_; ++i) {
4899 if (vis[i])
4900 continue;
4901
4902 vis[i] = true;
4903 q.push(i);
4904 comp_size.push_back(0);
4905 component_ids.emplace_back();
4906 while (q.size()) {
4907 int u = q.front();
4908 q.pop();
4909 ++comp_size.back();
4910 component_ids.back().push_back(u);
4911 for (int v : adj[u]) {
4912 if (!vis[v]) {
4913 vis[v] = true;
4914 q.push(v);
4915 }
4916 }
4917 }
4918 }
4919
4920 // Creates edges connecting the connected components by treating them as
4921 // vertices.
4922 std::vector<std::pair<int, int>> new_edges(edges_.begin(),
4923 edges_.end());
4924 if (comp_size.size() > 1) {
4925 std::vector<int> prufer_values =
4926 many_by_distribution(comp_size.size() - 2, comp_size);
4927 for (auto [u, v] : detail::edges_from_prufer(prufer_values))
4928 new_edges.emplace_back(pick(component_ids[u]),
4929 pick(component_ids[v]));
4930 }
4931
4932 return value(n_, new_edges);
4933 }
4934
4935 // Generates a (not uniformly) random skewed tree.
4936 // Vertex 0 is the root. For each i in 1 .. n-1, parent(i) is
4937 // wnext(i, elongation), i.e. a value in [0, i) with skew controlled by
4938 // elongation (see wnext).
4939 // If elongation is small enough, generates a star (center 0).
4940 // If elongation is large enough, generates a path (endpoints 0 and n-1).
4941 // O(n).
4942 static value gen_skewed(int n, int elongation) {
4943 std::vector<std::pair<int, int>> edges;
4944 for (int i = 1; i < n; ++i)
4945 edges.emplace_back(i, wnext<int>(i, elongation));
4946 return value(n, edges);
4947 }
4948
4949 // Kruskal-like random tree: random vertex pairs until connected.
4950 // Not uniformly random.
4951 // O(n log(n) alpha(n)) expected.
4952 static value gen_kruskal(int n) {
4953 tgen_ensure(n > 0, "wtree: gen_kruskal: n must be positive");
4954 if (n == 1)
4955 return value(1, {});
4956
4957 detail::dsu components(n);
4958 std::vector<std::pair<int, int>> edges;
4959 edges.reserve(n - 1);
4960 while (edges.size() < size_t(n - 1)) {
4961 int u = next(0, n - 1);
4962 int v = next(0, n - 1);
4963 if (u == v)
4964 continue;
4965 if (components.unite(u, v))
4966 edges.emplace_back(u, v);
4967 }
4968 return value(n, edges);
4969 }
4970};
4971
4972/*
4973 * Other types of weighted-ness.
4974 */
4975
4976// Vertex weighted tree.
4977template <typename VWeight> using vtree = wtree<VWeight, int>;
4978
4979// Edge weighted tree.
4980template <typename EWeight> using etree = wtree<int, EWeight>;
4981
4982// Unweighted tree.
4983using tree = wtree<int, int>;
4984
4985/*************
4986 * *
4987 * GRAPH *
4988 * *
4989 *************/
4990
4991namespace detail {
4992
4993// Canonical undirected edge key for duplicate detection; stores (min(u, v),
4994// max(u, v)). O(1).
4995inline uint64_t undirected_edge_key(int u, int v) {
4996 if (u > v)
4997 std::swap(u, v);
4998 return (static_cast<uint64_t>(u) << 32) |
4999 static_cast<uint64_t>(static_cast<uint32_t>(v));
5000}
5001
5002// Directed edge key for duplicate detection; stores (u, v).
5003// O(1).
5004inline uint64_t directed_edge_key(int u, int v) {
5005 return (static_cast<uint64_t>(u) << 32) |
5006 static_cast<uint64_t>(static_cast<uint32_t>(v));
5007}
5008
5009// Maximum number of edges in a simple graph on n vertices.
5010// O(1).
5011inline long long max_graph_edges(int n, bool directed, bool self_loops) {
5012 if (n <= 0)
5013 return 0;
5014 if (directed)
5015 return self_loops ? static_cast<long long>(n) * n
5016 : static_cast<long long>(n) * (n - 1);
5017 return self_loops ? static_cast<long long>(n) * (n + 1) / 2
5018 : static_cast<long long>(n) * (n - 1) / 2;
5019}
5020
5021// Uniform random edge for rejection sampling.
5022// O(1) expected.
5023inline std::pair<int, int> get_random_graph_edge(int n, bool directed,
5024 bool self_loops) {
5025 if (directed) {
5026 if (self_loops)
5027 return {next<int>(0, n - 1), next<int>(0, n - 1)};
5028 int u = next<int>(0, n - 1);
5029 int v = next<int>(0, n - 1);
5030 while (u == v)
5031 v = next<int>(0, n - 1);
5032 return {u, v};
5033 }
5034 if (self_loops) {
5035 int u = next<int>(0, n - 1);
5036 int v = next<int>(0, n - 1);
5037 if (u > v)
5038 std::swap(u, v);
5039 return {u, v};
5040 }
5041 int u = next<int>(0, n - 1);
5042 int v = next<int>(0, n - 1);
5043 while (u == v)
5044 v = next<int>(0, n - 1);
5045 if (u > v)
5046 std::swap(u, v);
5047 return {u, v};
5048}
5049
5050// Decodes a linear edge index to (u, v) for an undirected simple graph,
5051// with u < v.
5052// O(log n).
5053inline std::pair<int, int> decode_undirected_simple_edge(int n, long long idx) {
5054 auto base = [&](int u) -> long long {
5055 return static_cast<long long>(u) * (n - 1) -
5056 static_cast<long long>(u) * (u - 1) / 2;
5057 };
5058 int lo = 0, hi = n - 2;
5059 while (lo < hi) {
5060 int mid = (lo + hi + 1) / 2;
5061 if (base(mid) <= idx)
5062 lo = mid;
5063 else
5064 hi = mid - 1;
5065 }
5066 return {lo, lo + 1 + int(idx - base(lo))};
5067}
5068
5069// Decodes a linear edge index to (u, v) for an undirected graph with loops,
5070// with u <= v.
5071// O(log n).
5072inline std::pair<int, int> decode_undirected_loops_edge(int n, long long idx) {
5073 auto base = [&](int u) -> long long {
5074 return static_cast<long long>(u) * n -
5075 static_cast<long long>(u) * (u - 1) / 2;
5076 };
5077 int lo = 0, hi = n - 1;
5078 while (lo < hi) {
5079 int mid = (lo + hi + 1) / 2;
5080 if (base(mid) <= idx)
5081 lo = mid;
5082 else
5083 hi = mid - 1;
5084 }
5085 return {lo, lo + int(idx - base(lo))};
5086}
5087
5088// Decodes a linear edge index to (u, v) for a directed simple graph (no loops).
5089// O(1).
5090inline std::pair<int, int> decode_directed_simple_edge(int n, long long idx) {
5091 int u = idx / (n - 1);
5092 int rem = idx % (n - 1);
5093 return {u, rem + (rem >= u)};
5094}
5095
5096// Decodes a linear edge index according to graph mode.
5097// O(log n) for undirected, O(1) for directed.
5098inline std::pair<int, int>
5099decode_graph_edge_index(int n, long long idx, bool directed, bool self_loops) {
5100 if (directed) {
5101 if (self_loops)
5102 return {int(idx / n), int(idx % n)};
5103 return decode_directed_simple_edge(n, idx);
5104 }
5105 if (self_loops)
5106 return decode_undirected_loops_edge(n, idx);
5107 return decode_undirected_simple_edge(n, idx);
5108}
5109
5110} // namespace detail
5111
5112/*
5113 * Graph generator.
5114 *
5115 * Graphs of `n` vertices labeled from 0 to n-1 and `m` edges.
5116 * These are labeled graphs, that is, isomorphism is not taken into
5117 * account. VWeight is the type of vertex weights, and EWeight is the type of
5118 * edge weights. Generator does not generate weights. The weights are to be set
5119 * in the wgraph::value.
5120 */
5121
5122template <typename VWeight, typename EWeight>
5123struct wgraph : gen_base<wgraph<VWeight, EWeight>> {
5124 int n_, m_; // Number of vertices and edges.
5125 std::set<std::pair<int, int>> edges_; // Edges that were set.
5126 bool is_directed_; // If graph is directed.
5127 bool has_self_loops_; // If self-loops are allowed.
5128
5129 // Creates graph generator with `n` vertices and `m` edges.
5130 // Additionally, you can set if the graph is directed and if self loops are
5131 // allowed.
5132 // O(1).
5133 wgraph(int n, int m, bool is_directed = false, bool has_self_loops = false)
5134 : n_(n), m_(m), is_directed_(is_directed),
5135 has_self_loops_(has_self_loops) {
5136 tgen_ensure(n > 0, "wgraph: number of vertices must be positive");
5137 }
5138
5139 // Adds edge between u and v (this edge must be generated).
5140 // O(log m).
5141 wgraph &add_edge(int u, int v) {
5142 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,
5143 "wgraph: vertices must be indexed in [0, n)");
5144
5145 if (!is_directed_ and u > v)
5146 std::swap(u, v);
5147 edges_.emplace(u, v);
5148 tgen_ensure(static_cast<int>(edges_.size()) <= m_,
5149 "wgraph: too many edges were added");
5150 return *this;
5151 }
5152
5153 // Graph value.
5154 //
5155 // Edges are stored in both directions (if undirected) in adjacency list,
5156 // but only u < v in edge list.
5157 // Optimized for performance (lazy adjacency list; edge-list constructor
5158 // stores edges only).
5160 using std_type = std::tuple<int, int, std::vector<std::set<int>>>;
5161
5162 int n_; // Number of vertices.
5163 std::vector<std::set<int>> adj_; // Adjacency list.
5164 std::vector<std::pair<int, int>> edges_; // Edge list.
5165 bool is_directed_; // If graph is directed.
5166 bool add_1_; // If should add 1 for printing vertex ids.
5167 bool print_nm_; // If should print n and m.
5168 mutable bool adj_built_{
5169 false}; // Lazy cache: true once adj_ is built from edges_; mutable
5170 // so const adj() can populate it.
5171 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.
5172 std::optional<std::vector<EWeight>>
5173 edge_weights_; // Edge weights (in same order as edges_ ).
5174
5175 // Creates value from adjacency list. The edges
5176 // are considered to be directed.
5177 // O(n + m).
5178 value(const std::vector<std::set<int>> &adj, bool is_directed = false)
5179 : n_(static_cast<int>(adj.size())), adj_(adj),
5180 is_directed_(is_directed), add_1_(false), print_nm_(false),
5181 adj_built_(true) {
5182 for (int u = 0; u < n_; ++u)
5183 for (auto v : adj[u]) {
5185 0 <= v and v < n_,
5186 "wgraph: value: vertices must be indexed in [0, n)");
5187 // Undirected adjacency is symmetric: count each edge once
5188 // (canonical u <= v). Directed: every out-edge appears
5189 // once.
5190 if (is_directed_ or u <= v)
5191 edges_.emplace_back(u, v);
5192 }
5193 }
5194
5195 // Creates value from `n`, `m`, and edge list. The edges are
5196 // considered to be directed.
5197 // Optimized for performance (lazy adjacency list; unordered_set dedup).
5198 // O(m log m).
5199 value(int n, const std::vector<std::pair<int, int>> &edges = {},
5200 bool is_directed = false)
5201 : n_(n), edges_(), is_directed_(is_directed), add_1_(false),
5202 print_nm_(false), adj_built_(false) {
5203 edges_.reserve(edges.size());
5204 std::unordered_set<uint64_t> seen;
5205 seen.reserve(edges.size() * 2 + 1);
5206 for (auto [u, v] : edges) {
5208 0 <= std::min(u, v) and std::max(u, v) < n,
5209 "wgraph: value: vertices must be indexed in [0, n)");
5210 if (!is_directed_ and u > v)
5211 std::swap(u, v);
5212 uint64_t key = is_directed_ ? detail::directed_edge_key(u, v)
5213 : detail::undirected_edge_key(u, v);
5214 if (seen.insert(key).second)
5215 edges_.emplace_back(u, v);
5216 }
5217 }
5218 value(int n, const std::set<std::pair<int, int>> &edges,
5219 bool is_directed = false)
5220 : value(
5221 n,
5222 std::vector<std::pair<int, int>>(edges.begin(), edges.end()),
5223 is_directed) {}
5224 value(int n, const std::initializer_list<std::pair<int, int>> &edges,
5225 bool is_directed = false)
5226 : value(n, std::vector<std::pair<int, int>>(edges), is_directed) {}
5227
5228 // Creates graph from tree (undirected, same edges).
5229 // O(n).
5230 value(const typename wtree<VWeight, EWeight>::value &t)
5231 : value(t.n(), t.edges(), false) {
5232 if (t.vertex_weights().has_value()) {
5233 vertex_weights_ = *t.vertex_weights();
5234 }
5235 if (t.edge_weights().has_value()) {
5236 edge_weights_ = *t.edge_weights();
5237 }
5238 }
5239
5240 // Weight type conversion.
5241 // O(n + m).
5242 template <typename NewVWeight, typename NewEWeight>
5243 typename wgraph<NewVWeight, NewEWeight>::value
5244 convert_weight_types() const {
5245 tgen_ensure(!vertex_weights_.has_value() and
5246 !edge_weights_.has_value(),
5247 "wgraph: value: cannot convert weight type after "
5248 "assigning weights");
5249
5250 ensure_adj_built();
5251 typename wgraph<NewVWeight, NewEWeight>::value new_graph(
5252 adj_, is_directed_);
5253 new_graph.is_directed_ = is_directed_;
5254 new_graph.add_1_ = add_1_;
5255 new_graph.print_nm_ = print_nm_;
5256 return new_graph;
5257 }
5258
5259 // Fetches number of vertices.
5260 int n() const { return n_; }
5261
5262 // Fetches number of edges.
5263 int m() const { return edges_.size(); }
5264
5265 // Fetches if graph is directed;
5266 bool is_directed() const { return is_directed_; }
5267
5268 // Fetches a const ref. to adjacency list.
5269 const std::vector<std::set<int>> &adj() const {
5270 ensure_adj_built();
5271 return adj_;
5272 }
5273
5274 // Fetches a const ref. to edge set.
5275 const std::vector<std::pair<int, int>> &edges() const { return edges_; }
5276
5277 // Fetches vertex weights.
5279 return vertex_weights_;
5280 }
5281
5282 // Fetches edge weights.
5284 return edge_weights_;
5285 }
5286
5287 // Sets vertex weights.
5288 // O(n + m).
5289 template <typename NewVWeight = VWeight>
5290 typename wgraph<NewVWeight, EWeight>::value set_vertex_weights(
5291 const std::vector<NewVWeight> &vertex_weights) const {
5292 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),
5293 "wgraph: value: must give `n` vertex weights");
5294
5295 auto new_graph = convert_weight_types<NewVWeight, EWeight>();
5296 new_graph.vertex_weights_ = vertex_weights;
5297 return new_graph;
5298 }
5299
5300 // Sets edge weights.
5301 // O(n + m).
5302 template <typename NewEWeight = EWeight>
5303 typename wgraph<VWeight, NewEWeight>::value
5304 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {
5305 tgen_ensure(static_cast<int>(edge_weights.size()) == m(),
5306 "wgraph: value: must give `m` edge weights");
5307
5308 auto new_graph = convert_weight_types<VWeight, NewEWeight>();
5309 new_graph.edge_weights_ = edge_weights;
5310 return new_graph;
5311 }
5312
5313 // Enables edge-weighted mode before adding weighted edges
5314 // incrementally. The graph must have no edges yet. O(1).
5316 tgen_ensure(m() == 0,
5317 "wgraph: value: edge_weighted requires a graph with no "
5318 "edges");
5319 tgen_ensure(!edge_weights_.has_value(),
5320 "wgraph: value: graph is already edge-weighted");
5321
5322 edge_weights_ = std::vector<EWeight>();
5323 return *this;
5324 }
5325
5326 // Adds 1 to vertex ids, for printing.
5327 // O(1).
5329 add_1_ = true;
5330 return *this;
5331 }
5332
5333 // Prints `n m` on a new line before printing the edges.
5334 // O(1).
5336 print_nm_ = true;
5337 return *this;
5338 }
5339
5340 // Shuffles the graph's vertex labels (except those in `indices`,
5341 // which keep their current label) and edge order. The change is
5342 // applied eagerly to the underlying adjacency list, edge list,
5343 // vertex weights and edge weights.
5344 // O(n + m).
5345 value &shuffle_except(std::set<int> indices) {
5346 ensure_adj_built();
5347 // Builds the relabeling: for each vertex `i`, `new_label[i]` is
5348 // its new id. Vertices in `indices` keep their label; the others
5349 // are permuted among themselves.
5350 std::vector<int> new_label(n());
5351 std::vector<int> shuffled;
5352 for (int i = 0; i < n(); ++i) {
5353 if (indices.count(i))
5354 new_label[i] = i;
5355 else
5356 shuffled.push_back(i);
5357 }
5358 std::vector<int> targets = shuffled;
5359 tgen::shuffle(targets.begin(), targets.end());
5360 for (size_t k = 0; k < shuffled.size(); ++k)
5361 new_label[shuffled[k]] = targets[k];
5362
5363 // Rewrites adjacency list with new labels.
5364 std::vector<std::set<int>> new_adj(n());
5365 for (int u = 0; u < n(); ++u)
5366 for (int v : adj_[u])
5367 new_adj[new_label[u]].insert(new_label[v]);
5368 adj_ = new_adj;
5369
5370 // Rewrites edges with new labels (canonical undirected order).
5371 for (auto &[u, v] : edges_) {
5372 u = new_label[u];
5373 v = new_label[v];
5374 if (!is_directed_ and u > v)
5375 std::swap(u, v);
5376 }
5377
5378 // Permutes vertex weights to match the new labels.
5379 if (vertex_weights_.has_value()) {
5380 std::vector<VWeight> new_vw(n());
5381 for (int i = 0; i < n(); ++i)
5382 new_vw[new_label[i]] = (*vertex_weights_)[i];
5383 vertex_weights_ = new_vw;
5384 }
5385
5386 // Shuffles edge order, keeping edge weights aligned.
5387
5388 std::vector<int> perm(edges_.size());
5389 std::iota(perm.begin(), perm.end(), 0);
5390 tgen::shuffle(perm.begin(), perm.end());
5391
5392 std::vector<std::pair<int, int>> new_edges;
5393 std::optional<std::vector<EWeight>> new_ew;
5394 if (edge_weights_.has_value())
5395 new_ew = std::vector<EWeight>();
5396 for (int i : perm) {
5397 new_edges.push_back(edges_[i]);
5398 if (new_ew.has_value())
5399 new_ew->push_back((*edge_weights_)[i]);
5400 }
5401
5402 edges_ = new_edges;
5403 if (new_ew.has_value())
5404 edge_weights_ = new_ew;
5405
5406 return *this;
5407 }
5408
5409 // Shuffles the graph's vertices and edge order.
5410 // O(n + m).
5411 value &shuffle() { return shuffle_except({}); }
5412
5413 // Adds `k` vertices to the graph (labeled n, n+1, ...n+k-1). Updates
5414 // `n` accordingly.
5415 // O(k) amortized.
5416 value &add_vertices(int k, std::optional<std::vector<VWeight>>
5417 new_vertex_weights = std::nullopt) {
5418 ensure_adj_built();
5419 n_ += k;
5420 adj_.resize(n());
5421 if (new_vertex_weights.has_value()) {
5422 tgen_ensure(vertex_weights().has_value(),
5423 "wgraph: value: cannot add weighted vertices to "
5424 "vertex-unweighted graph");
5426 static_cast<int>(new_vertex_weights->size()) == k,
5427 "wgraph: value: number of vertex weights must be equal "
5428 "to number of added vertices");
5429
5430 vertex_weights_->insert(vertex_weights_->end(),
5431 new_vertex_weights->begin(),
5432 new_vertex_weights->end());
5433 } else
5434 tgen_ensure(!vertex_weights().has_value(),
5435 "wgraph: value: cannot add unweighted vertices to "
5436 "vertex-weighted graph");
5437
5438 return *this;
5439 }
5440
5441 // Adds edge (u, v).
5442 // O(log n) amortized.
5443 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {
5444 ensure_adj_built();
5445 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),
5446 "wgraph: value: vertex ids must be valid");
5447
5448 if (!is_directed() and u > v)
5449 std::swap(u, v);
5450
5451 if (adj_[u].count(v))
5452 return *this;
5453
5454 adj_[u].insert(v);
5455 if (!is_directed())
5456 adj_[v].insert(u);
5457 edges_.emplace_back(u, v);
5458
5459 if (w.has_value()) {
5460 tgen_ensure(edge_weights().has_value(),
5461 "wgraph: value: cannot add weighted edge to "
5462 "edge-unweighted graph");
5463
5464 edge_weights_->push_back(*w);
5465 } else
5466 tgen_ensure(!edge_weights().has_value(),
5467 "wgraph: value: cannot add unweighted edge to "
5468 "edge-weighted graph");
5469
5470 return *this;
5471 }
5472
5473 // Links graph with another `rhs`, adding the edge between u (in left
5474 // graph) and v (in right graph). Ids for added vertices are updated
5475 // accordingly.
5476 // O(rhs.n + rhs.m * log n) amortized.
5477 value &link(const value &rhs, int new_u, int new_v,
5478 std::optional<EWeight> new_w = std::nullopt) {
5479 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and
5480 new_v < rhs.n(),
5481 "wgraph: value: vertex ids must be valid");
5482
5483 // Edges from right-hand side.
5484 int shift = n();
5485 add_vertices(rhs.n(), rhs.vertex_weights());
5486 for (int i = 0; i < rhs.m(); ++i) {
5487 auto [u, v] = rhs.edges()[i];
5488 add_edge(shift + u, shift + v,
5489 rhs.edge_weights().has_value()
5490 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5491 : std::nullopt);
5492 }
5493
5494 // New edge.
5495 add_edge(new_u, shift + new_v, new_w);
5496
5497 return *this;
5498 }
5499
5500 // Glues the graph with another `rhs` such that index_pairs[i].first is
5501 // considered to be the same as index_pairs[i].second. Ids for added
5502 // vertices are updated accordingly.
5503 // O(rhs.n + rhs.m * log n) amortized.
5504 value &glue(const value &rhs,
5505 std::set<std::pair<int, int>> index_pairs) {
5508 "wgraph: value: graphs must have the same is_directed value");
5509
5510 // Checks validity of indices.
5511 std::set<int> idx_left, idx_right;
5512 std::vector<int> right_id_to_left(rhs.n(), -1);
5513 for (auto [l, r] : index_pairs) {
5515 0 <= l and l < n() and 0 <= r and r < rhs.n(),
5516 "wgraph: value: vertex indices to glue must be valid");
5517 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,
5518 "wgraph: value: must not have repeated indices "
5519 "on the same side to glue");
5520
5521 idx_left.insert(l);
5522 idx_right.insert(r);
5523 right_id_to_left[r] = l;
5524 }
5525
5526 // Computes new ids of right vertices.
5527 std::vector<int> new_right_id(rhs.n(), -1);
5528 int intersection_lt = 0;
5529 std::optional<std::vector<VWeight>> rhs_vertex_weights;
5530 for (int i = 0; i < rhs.n(); ++i) {
5531 if (right_id_to_left[i] != -1) {
5532 // Is in intersection.
5533 ++intersection_lt;
5534 new_right_id[i] = right_id_to_left[i];
5535 } else {
5536 // New id.
5537 new_right_id[i] = n() + i - intersection_lt;
5538 if (rhs.vertex_weights().has_value()) {
5539 if (!rhs_vertex_weights.has_value())
5540 rhs_vertex_weights = std::vector<VWeight>();
5541 rhs_vertex_weights->push_back(
5542 (*rhs.vertex_weights())[i]);
5543 }
5544 }
5545 }
5546
5547 // Adds new vertices and edges.
5548 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
5549 for (int i = 0; i < rhs.m(); ++i) {
5550 auto [u, v] = rhs.edges()[i];
5551 add_edge(new_right_id[u], new_right_id[v],
5552 rhs.edge_weights().has_value()
5553 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5554 : std::nullopt);
5555 }
5556
5557 return *this;
5558 }
5559 value &glue(const value &rhs,
5560 std::initializer_list<std::pair<int, int>> il) {
5561 return glue(rhs, std::set<std::pair<int, int>>(il));
5562 }
5563
5564 // Glues the graph with another `rhs` at `indices`. That is, idx in
5565 // `indices` are considered to be the same vertex. Ids for added
5566 // vertices are updated accordingly.
5567 // O(rhs.n + rhs.m * log n) amortized.
5568 value &glue(const value &rhs, std::set<int> indices) {
5569 std::set<std::pair<int, int>> index_pairs;
5570 for (auto i : indices)
5571 index_pairs.emplace(i, i);
5572 return glue(rhs, index_pairs);
5573 }
5574 value &glue(const value &rhs, const std::initializer_list<int> &il) {
5575 return glue(rhs, std::set<int>(il));
5576 }
5577
5578 // Disjoint union.
5579 // Shifts ids from `rhs` graph by n().
5580 // O(rhs.n + rhs.m * log n) amortized.
5582 return glue(rhs, std::set<int>());
5583 }
5584
5585 // Computes uniformly random subgraph of graph with num_edges edges.
5586 // O(n + m).
5587 value &random_subgraph(int num_edges) {
5589 num_edges <= m(),
5590 "wgraph: value: can choose at most `m` edges from graph");
5591
5592 std::vector<std::pair<int, int>> new_edges;
5593 std::optional<std::vector<EWeight>> new_edge_weights;
5594
5595 int left = m();
5596 for (int i = 0; i < m(); ++i) {
5597 if (next(1, left--) <= num_edges) {
5598 new_edges.push_back(edges()[i]);
5599 if (edge_weights_.has_value()) {
5600 if (!new_edge_weights.has_value())
5601 new_edge_weights = std::vector<EWeight>();
5602 new_edge_weights->push_back((*edge_weights())[i]);
5603 }
5604 --num_edges;
5605 }
5606 }
5607
5608 edges_ = new_edges;
5609 edge_weights_ = new_edge_weights;
5610 rebuild_adj_from_edge_list();
5611 return *this;
5612 }
5613
5614 // Computes a random (not uniform) subgraph with `num_edges` edges that
5615 // keeps every connected component connected (does not increase the
5616 // number of connected components).
5617 // 1. Picks a spanning forest via randomized Prim.
5618 // 2. Adds additional edges uniformly at random.
5619 // O(n + m).
5621 tgen_ensure(!is_directed_,
5622 "wgraph: value: random_connected_subgraph is only for "
5623 "undirected graphs");
5625 num_edges <= m(),
5626 "wgraph: value: can choose at most `m` edges from graph");
5627
5628 // Builds an incidence list: for each vertex, the (neighbor, edge
5629 // index) pairs.
5630 std::vector<std::vector<std::pair<int, int>>> incident(n());
5631 for (int i = 0; i < m(); ++i) {
5632 auto [u, v] = edges_[i];
5633 incident[u].emplace_back(v, i);
5634 incident[v].emplace_back(u, i);
5635 }
5636
5637 // Randomized Prim.
5638 std::vector<bool> vis(n(), false);
5639 std::vector<int> queue;
5640 std::vector<bool> in_tree(m(), false);
5641 int forest_edges = 0;
5642
5643 for (int start = 0; start < n(); ++start) {
5644 if (vis[start])
5645 continue;
5646 vis[start] = true;
5647 queue.push_back(start);
5648
5649 while (!queue.empty()) {
5650 int i = tgen::next<int>(0, queue.size() - 1);
5651 int u = queue[i];
5652 std::swap(queue[i], queue.back());
5653 queue.pop_back();
5654
5655 for (auto [v, edge_idx] : incident[u]) {
5656 if (!vis[v]) {
5657 vis[v] = true;
5658 queue.push_back(v);
5659 in_tree[edge_idx] = true;
5660 ++forest_edges;
5661 }
5662 }
5663 }
5664 }
5666 num_edges >= forest_edges,
5667 "wgraph: value: random_connected_subgraph needs at least "
5668 "`n - c` edges, where `c` is the number of connected "
5669 "components");
5670
5671 // Splits edge indices into forest edges and the rest.
5672 std::vector<int> tree_idx, rest_idx;
5673 for (int i = 0; i < m(); ++i) {
5674 if (in_tree[i])
5675 tree_idx.push_back(i);
5676 else
5677 rest_idx.push_back(i);
5678 }
5679
5680 tgen::shuffle(rest_idx.begin(), rest_idx.end());
5681
5682 std::vector<int> chosen_idx;
5683 chosen_idx.insert(chosen_idx.end(), tree_idx.begin(),
5684 tree_idx.end());
5685 chosen_idx.insert(chosen_idx.end(), rest_idx.begin(),
5686 rest_idx.begin() + num_edges - forest_edges);
5687
5688 detail::tgen_ensure_against_bug(
5689 static_cast<int>(chosen_idx.size()) == num_edges,
5690 "wgraph: value: chose a wrong number of edges");
5691
5692 std::vector<std::pair<int, int>> new_edges;
5693 std::optional<std::vector<EWeight>> new_edge_weights;
5694 if (edge_weights_.has_value())
5695 new_edge_weights = std::vector<EWeight>();
5696 for (int i : chosen_idx) {
5697 new_edges.push_back(edges_[i]);
5698 if (new_edge_weights.has_value())
5699 new_edge_weights->push_back((*edge_weights_)[i]);
5700 }
5701
5702 edges_ = new_edges;
5703 edge_weights_ = new_edge_weights;
5704 rebuild_adj_from_edge_list();
5705 return *this;
5706 }
5707
5708 // Complement. Self loops are maintained.
5709 // O(n^2).
5710 value operator!() const {
5711 tgen_ensure(!edge_weights_.has_value(),
5712 "wgraph: value: cannot compute complement of "
5713 "edge-weighted graph");
5714
5715 value complement = *this;
5716 complement.ensure_adj_built();
5717 std::vector<std::pair<int, int>> compl_edges;
5718 for (int i = 0; i < complement.n_; ++i) {
5719 std::set<int> complement_adj;
5720 for (int j = 0; j < complement.n_; ++j) {
5721 bool add_j = false;
5722 if (j == i and complement.adj_[i].count(j))
5723 add_j = true;
5724 if (j != i and !complement.adj_[i].count(j))
5725 add_j = true;
5726
5727 if (add_j) {
5728 complement_adj.insert(j);
5729 // If i > j and !is_directed(), we don't add the edge.
5730 if (i <= j or complement.is_directed_) {
5731 compl_edges.emplace_back(i, j);
5732 }
5733 }
5734 }
5735 std::swap(complement.adj_[i], complement_adj);
5736 }
5737 std::swap(complement.edges_, compl_edges);
5738
5739 return complement;
5740 }
5741
5742 // Concatenates two values.
5743 // O(N + M log N), N = n + rhs.n, M = m + rhs.m.
5744 value operator+(const value &rhs) const {
5746 "wgraph: value: graphs must have the same "
5747 "is_directed value");
5748
5749 tgen_ensure(vertex_weights().has_value() ==
5750 rhs.vertex_weights().has_value(),
5751 "wgraph: value: cannot concatenate vertex-weighted "
5752 "wgraph to unweighted");
5753 tgen_ensure(edge_weights().has_value() ==
5754 rhs.edge_weights().has_value(),
5755 "wgraph: value: cannot concatenate edge-weighted "
5756 "wgraph to unweighted");
5757
5758 value concat = *this;
5759 concat.glue(rhs, std::set<std::pair<int, int>>());
5760 concat.add_1_ = add_1_ | rhs.add_1_;
5761 concat.print_nm_ = print_nm_ | rhs.print_nm_;
5762
5763 return concat;
5764 }
5765
5766 // Prints to std::ostream.
5767 // O(n + m).
5768 friend std::ostream &operator<<(std::ostream &out, const value &val) {
5769 // Prints `n` and `m`.
5770 if (val.print_nm_)
5771 out << val.n() << " " << val.m() << '\n';
5772
5773 // Prints vertex weights.
5774 if (val.vertex_weights()) {
5775 for (int i = 0; i < val.n(); ++i) {
5776 if (i > 0)
5777 out << " ";
5778 out << (*val.vertex_weights())[i];
5779 }
5780 out << '\n';
5781 }
5782
5783 // Prints edges.
5784 for (int i = 0; i < val.m(); ++i) {
5785 auto [u, v] = val.edges()[i];
5786 out << (u + val.add_1_) << " " << (v + val.add_1_);
5787
5788 // Edge weight.
5789 if (val.edge_weights().has_value())
5790 out << " " << (*val.edge_weights())[i];
5791
5792 out << '\n';
5793 }
5794
5795 return out;
5796 }
5797
5798 // Gets a std::tuple<n, m, adj> representing the value.
5799 std::tuple<int, int, std::vector<std::set<int>>> to_std() const {
5800 ensure_adj_built();
5801 return std_type(n_, m(), adj_);
5802 }
5803
5804 private:
5805 // Rebuilds adjacency from edges_ after replacing the edge list (e.g.
5806 // subgraph operations).
5807 // O(m log n).
5808 void rebuild_adj_from_edge_list() {
5809 adj_.assign(n_, {});
5810 for (auto [u, v] : edges_) {
5811 adj_[u].insert(v);
5812 if (!is_directed_)
5813 adj_[v].insert(u);
5814 }
5815 adj_built_ = true;
5816 }
5817
5818 // Builds adj_ from edges_ on first use.
5819 // O(1) if already built; O(m log n) otherwise.
5820 void ensure_adj_built() const {
5821 if (adj_built_)
5822 return;
5823 const_cast<value *>(this)->rebuild_adj_from_edge_list();
5824 }
5825 };
5826
5827 // Adds all edges from `rhs` as preset edges.
5828 // O(rhs.m * log m).
5830 tgen_ensure(is_directed_ == rhs.is_directed(),
5831 "wgraph: graphs must have the same is_directed value");
5832
5833 for (auto [u, v] : rhs.edges())
5834 add_edge(u, v);
5835 return *this;
5836 }
5837
5838 // Generates graph value.
5839 // Optimized for performance: dense no-preset graphs use index sampling;
5840 // otherwise gen_remaining_edges.
5841 // O(n + m log^2 n) expected.
5842 value gen() const {
5843 detail::tgen_ensure_against_bug(static_cast<int>(edges_.size()) <= m_,
5844 "wgraph: too many edges were added");
5845
5846 // All edges already added.
5847 if (static_cast<int>(edges_.size()) == m_)
5848 return value(n_, edges_, is_directed_);
5849
5850 // Splits into two cases to optimize performance.
5851
5852 // No presets and m > max_edges / 2: sample m distinct edge indices.
5853 if (auto indexed = try_gen_by_edge_index())
5854 return *indexed;
5855
5856 // Otherwise: fill preset edges up to m_ with uniform random edges.
5857 return gen_remaining_edges(
5858 std::vector<std::pair<int, int>>(edges_.begin(), edges_.end()));
5859 }
5860
5861 // Gets a (not uniformly) random connected undirected graph.
5862 // 1. Preset edges induce a spanning forest on their components.
5863 // 2. Then, uniformly random edges between components are added.
5864 // 3. Remaining edges are added uniformly at random.
5865 // O(n + m log^2 n) expected.
5867 tgen_ensure(!is_directed_,
5868 "wgraph: get_connected is only for undirected graphs");
5869 tgen_ensure(m_ >= n_ - 1,
5870 "wgraph: connected graph needs at least n - 1 edges");
5871
5872 std::vector<std::pair<int, int>> edges;
5873 edges.reserve(m_);
5874
5875 if (edges_.empty()) {
5876 if (n_ > 1) {
5877 std::vector<int> prufer(n_ - 2);
5878 for (int i = 0; i < n_ - 2; ++i)
5879 prufer[i] = next<int>(0, n_ - 1);
5880 for (auto [u, v] : detail::edges_from_prufer(std::move(prufer)))
5881 edges.emplace_back(u, v);
5882 }
5883 } else {
5884 edges.assign(edges_.begin(), edges_.end());
5885
5886 std::vector<std::vector<int>> adj(n_);
5887 for (auto [u, v] : edges_) {
5888 adj[u].push_back(v);
5889 adj[v].push_back(u);
5890 }
5891
5892 std::vector<int> comp_size;
5893 std::vector<std::vector<int>> component_ids;
5894 std::vector<bool> vis(n_, false);
5895 std::queue<int> q;
5896
5897 for (int i = 0; i < n_; ++i) {
5898 if (vis[i])
5899 continue;
5900
5901 vis[i] = true;
5902 q.push(i);
5903 comp_size.push_back(0);
5904 component_ids.emplace_back();
5905 while (q.size()) {
5906 int u = q.front();
5907 q.pop();
5908 ++comp_size.back();
5909 component_ids.back().push_back(u);
5910 for (int v : adj[u]) {
5911 if (!vis[v]) {
5912 vis[v] = true;
5913 q.push(v);
5914 }
5915 }
5916 }
5917 }
5918
5919 if (component_ids.size() > 1) {
5920 std::vector<int> prufer_values =
5921 many_by_distribution(component_ids.size() - 2, comp_size);
5922 for (auto [u, v] :
5923 detail::edges_from_prufer(std::move(prufer_values)))
5924 edges.emplace_back(pick(component_ids[u]),
5925 pick(component_ids[v]));
5926 }
5927 }
5928
5929 return gen_remaining_edges(std::move(edges));
5930 }
5931
5932 // Gets a (not uniformly) random directed acyclic graph.
5933 // 1. Randomized Kahn (uniform choice among indegree-0 vertices) yields a
5934 // random topological order of the preset edges (which must be acyclic).
5935 // 2. Extra edges are sampled randomly using the order.
5936 // With no preset edges: sample a random graph then orient acyclically.
5937 // Optimized for performance (distinct upper-triangle edge-index sampling;
5938 // rejection instead of pair::distinct for preset edges).
5939 // O(n + m log^2 n) expected.
5941 tgen_ensure(is_directed_,
5942 "wgraph: get_acyclic is only for directed graphs");
5943
5944 if (edges_.empty()) {
5945 std::vector<int> order(n_);
5946 std::iota(order.begin(), order.end(), 0);
5947 for (int i = n_ - 1; i > 0; --i)
5948 std::swap(order[i], order[next(0, i)]);
5949
5950 const long long max_pairs =
5951 static_cast<long long>(n_) * (n_ - 1) / 2;
5952 tgen_ensure(m_ <= max_pairs,
5953 "wgraph: not enough edges to generate");
5954
5955 std::vector<std::pair<int, int>> edges;
5956 edges.reserve(m_);
5957 for (long long idx : distinct_range<long long>(0, max_pairs - 1)
5958 .gen_list(m_)
5959 .to_std()) {
5960 auto [i, j] = detail::decode_undirected_simple_edge(n_, idx);
5961 edges.emplace_back(order[i], order[j]);
5962 }
5963 return value(n_, edges, true);
5964 }
5965
5966 std::vector<std::vector<int>> adj(n_);
5967 std::vector<int> indeg(n_, 0);
5968 for (auto [u, v] : edges_) {
5969 adj[u].push_back(v);
5970 ++indeg[v];
5971 }
5972
5973 std::vector<int> available;
5974 for (int i = 0; i < n_; ++i)
5975 if (indeg[i] == 0)
5976 available.push_back(i);
5977
5978 // Random topological order using randomized Kahn's algorithm.
5979 std::vector<int> order;
5980 while (!available.empty()) {
5981 int idx = next(0, static_cast<int>(available.size()) - 1);
5982 int u = available[idx];
5983 std::swap(available[idx], available.back());
5984 available.pop_back();
5985
5986 order.push_back(u);
5987 for (int v : adj[u])
5988 if (--indeg[v] == 0)
5989 available.push_back(v);
5990 }
5991
5992 tgen_ensure(static_cast<int>(order.size()) == n_,
5993 "wgraph: preset edges contain a directed cycle");
5994
5995 value acyclic(n_, edges_, true);
5996
5997 // Generates final edges.
5998
5999 detail::tgen_ensure_against_bug(acyclic.m() <= m_,
6000 "wgraph: too many edges were added");
6001
6002 if (acyclic.m() < m_) {
6003 std::vector<int> order_pos(n_);
6004 for (int i = 0; i < n_; ++i)
6005 order_pos[order[i]] = i;
6006
6007 std::unordered_set<uint64_t> seen;
6008 seen.reserve(m_ * 2);
6009 for (auto [u, v] : acyclic.edges())
6010 seen.insert(
6011 detail::undirected_edge_key(order_pos[u], order_pos[v]));
6012
6013 const long long max_pairs =
6014 static_cast<long long>(n_) * (n_ - 1) / 2;
6015 while (acyclic.m() < m_) {
6016 std::pair<int, int> edge;
6017 if (!detail::try_generate_distinct(seen, [&] {
6018 long long idx = next<long long>(0, max_pairs - 1);
6019 edge = detail::decode_undirected_simple_edge(n_, idx);
6020 return detail::undirected_edge_key(edge.first,
6021 edge.second);
6022 }))
6023 throw detail::error("wgraph: not enough edges to generate");
6024 acyclic.add_edge(order[edge.first], order[edge.second]);
6025 }
6026 }
6027
6028 return acyclic;
6029 }
6030
6031 // Generates a (not uniformly) random skewed connected graph.
6032 // 1. Builds the same skewed labeled tree as wtree::gen_skewed(n,
6033 // elongation)(root 0, parent(i) = wnext(i, elongation) for i >= 1).
6034 // If is_directed, tree edges are oriented down the tree.
6035 // 2. Adds the remaining edges: pick an endpoint u uniformly;
6036 // pick k uniformly in [1, spread]; walk from u toward the root k
6037 // times along tree parents to get v; add edge (v, u).
6038 // If elongation is small, generates a graph with small diameter.
6039 // If elongation is large, generates a graph with large diameter, with
6040 // vertices 0 and n-1 being far apart.
6041 // O(n + m log n) if spread is O(1);
6042 // O(n log n + m log^2 n) expected otherwise.
6043 static value gen_skewed(int n, int m, int elongation, int spread,
6044 bool is_directed = false) {
6046 m >= n - 1,
6047 "wgraph: skewed graph needs at least n - 1 edges to be connected");
6048 tgen_ensure(spread >= 2,
6049 "wgraph: gen_skewed spread must be at least 2");
6050
6051 value skewed(n, {}, is_directed);
6052
6053 std::vector<int> parent(n), depth(n, 0);
6054 parent[0] = 0;
6055 for (int i = 1; i < n; ++i) {
6056 int p = wnext<int>(i, elongation);
6057 parent[i] = p;
6058 depth[i] = depth[p] + 1;
6059 skewed.add_edge(p, i);
6060 }
6061
6062 const int extra = m - (n - 1);
6063 if (extra == 0)
6064 return skewed;
6065
6066 // If spread is large, use binary lifting to find the ancestor.
6067 // Otherwise, enumerate O(n * spread) ancestor edges and sample
6068 // directly.
6069 constexpr int naive_ancestor_spread = 20;
6070
6071 if (spread <= naive_ancestor_spread) {
6072 std::vector<std::pair<int, int>> candidates;
6073 candidates.reserve(n * spread);
6074 for (int u = 0; u < n; ++u) {
6075 int max_k = std::min(spread, depth[u]);
6076 if (max_k < 2)
6077 continue;
6078 int v = parent[u];
6079 for (int k = 2; k <= max_k; ++k) {
6080 v = parent[v];
6081 candidates.emplace_back(v, u);
6082 }
6083 }
6084
6085 tgen_ensure(extra <= static_cast<int>(candidates.size()),
6086 "wgraph: not enough edges to generate");
6087
6088 for (auto [v, u] : choose(candidates, extra))
6089 skewed.add_edge(v, u);
6090 } else {
6091 // Binary lifting.
6092 int lg = 1;
6093 while ((1 << lg) <= n)
6094 ++lg;
6095
6096 std::vector<std::vector<int>> up(lg, std::vector<int>(n));
6097 for (int v = 0; v < n; ++v)
6098 up[0][v] = parent[v];
6099 for (int j = 1; j < lg; ++j)
6100 for (int v = 0; v < n; ++v)
6101 up[j][v] = up[j - 1][up[j - 1][v]];
6102
6103 // Creates uniform generator of edges (u, v) such that v is ancestor
6104 // of u. For that, every u has depth[u]-1 choices for v, so we
6105 // weight u by min(spread - 1, depth[u] - 1). After that we can
6106 // just pick the ancestor uniformly.
6107 std::vector<int> distribution = depth;
6108 for (int &d : distribution)
6109 d = std::max(0, std::min(spread - 1, d - 1));
6110 weighted_sampler vertex_choice(distribution);
6111 distinct extra_edges([&]() -> std::pair<int, int> {
6112 int u = vertex_choice.next();
6113 int k = next(2, spread);
6114 int v = u;
6115 for (int j = 0; j < lg; ++j)
6116 if (k >> j & 1)
6117 v = up[j][v];
6118 return {v, u};
6119 });
6120
6121 while (skewed.m() < m) {
6122 std::pair<int, int> edge;
6123 try {
6124 edge = extra_edges.gen();
6125 } catch (const std::runtime_error &e) {
6126 if (std::string(e.what()) ==
6127 "tgen: distinct: no more distinct values")
6128 throw detail::error(
6129 "wgraph: not enough edges to generate");
6130 throw e;
6131 }
6132
6133 skewed.add_edge(edge.first, edge.second);
6134 }
6135 }
6136
6137 return skewed;
6138 }
6139
6140 // Generates a random bipartite graph. The first side has vertices
6141 // 0 .. n1-1, the second n1 .. n1+n2-1.
6142 // Uniform when connected is false (distinct cross-edge indices).
6143 // When connected, bipartite Prüfer + rejection fill; not uniform over
6144 // connected bipartite graphs.
6145 // O(n1 + n2 + m log(n1 * n2)) expected.
6146 static value gen_bipartite(int n1, int n2, int m, bool connected = false) {
6147 tgen_ensure(m >= 0, "wgraph: number of edges must be nonnegative");
6148 long long num_edges = 1LL * n1 * n2;
6149 tgen_ensure(m <= num_edges,
6150 "wgraph: bipartite graph has at most n1 * n2 edges");
6151 if (connected)
6153 m >= n1 + n2 - 1,
6154 "wgraph: connected bipartite graph needs at least n1 + n2 - 1 "
6155 "edges");
6156
6157 if (!connected) {
6158 std::vector<std::pair<int, int>> edges;
6159 edges.reserve(m);
6160 for (long long idx : distinct_range<long long>(0, num_edges - 1)
6161 .gen_list(m)
6162 .to_std())
6163 edges.emplace_back(static_cast<int>(idx / n2),
6164 n1 + static_cast<int>(idx % n2));
6165 return value(n1 + n2, std::move(edges), false);
6166 }
6167
6168 std::unordered_set<uint64_t> used_edges;
6169 used_edges.reserve(m * 2);
6170 std::vector<std::pair<int, int>> edges;
6171 edges.reserve(m);
6172
6173 auto pack_edge = [](int u, int v) -> uint64_t {
6174 if (u > v)
6175 std::swap(u, v);
6176 return (static_cast<uint64_t>(u) << 32) | static_cast<uint32_t>(v);
6177 };
6178
6179 if (n1 > 0 and n2 > 0) {
6180 std::vector<int> prufer(n1 + n2 - 2);
6181 for (int i = 0; i < n2 - 1; ++i)
6182 prufer[i] = next(0, n1 - 1);
6183 for (int i = 0; i < n1 - 1; ++i)
6184 prufer[n2 - 1 + i] = next(n1, n1 + n2 - 1);
6185 shuffle(prufer.begin(), prufer.end());
6186 for (auto [u, v] : detail::edges_from_prufer(std::move(prufer))) {
6187 if (u > v)
6188 std::swap(u, v);
6189 if (used_edges.insert(pack_edge(u, v)).second)
6190 edges.emplace_back(u, v);
6191 }
6192 detail::tgen_ensure_against_bug(
6193 used_edges.size() == size_t(n1 + n2 - 1),
6194 "wgraph: invalid bipartite spanning tree size");
6195 }
6196
6197 while (edges.size() < size_t(m)) {
6198 int u = next(0, n1 - 1);
6199 int v = next(n1, n1 + n2 - 1);
6200 if (used_edges.insert(pack_edge(u, v)).second)
6201 edges.emplace_back(u, v);
6202 }
6203
6204 return value(n1 + n2, std::move(edges), false);
6205 }
6206
6207 private:
6208 // If this generator has no preset edges and m is large relative to the
6209 // maximum edge count, sample by distinct edge index. Otherwise
6210 // std::nullopt.
6211 // Optimized for performance (index sampling instead of rejection).
6212 // O(m log n).
6213 std::optional<value> try_gen_by_edge_index() const {
6214 if (!edges_.empty())
6215 return std::nullopt;
6216
6217 long long max_edges =
6218 detail::max_graph_edges(n_, is_directed_, has_self_loops_);
6219 if (m_ > max_edges)
6220 throw detail::error("wgraph: not enough edges to generate");
6221 if (max_edges <= 0 or 2LL * m_ <= max_edges)
6222 return std::nullopt;
6223
6224 std::vector<std::pair<int, int>> edges;
6225 edges.reserve(m_);
6226 for (long long idx :
6227 distinct_range<long long>(0, max_edges - 1).gen_list(m_).to_std())
6228 edges.push_back(detail::decode_graph_edge_index(
6229 n_, idx, is_directed_, has_self_loops_));
6230
6231 return value(n_, edges, is_directed_);
6232 }
6233
6234 // Fills `edges` up to m_ with uniform random edges not already present.
6235 // Optimized for performance (uint64 edge keys + try_generate_distinct).
6236 // O(m log^2 n) expected.
6237 value gen_remaining_edges(std::vector<std::pair<int, int>> edges) const {
6238 detail::tgen_ensure_against_bug(static_cast<int>(edges.size()) <= m_,
6239 "wgraph: too many edges were added");
6240
6241 if (static_cast<int>(edges.size()) == m_)
6242 return value(n_, edges, is_directed_);
6243
6244 edges.reserve(m_);
6245
6246 std::unordered_set<uint64_t> seen;
6247 seen.reserve(m_ * 2);
6248 for (auto [u, v] : edges) {
6249 if (!is_directed_ and u > v)
6250 std::swap(u, v);
6251 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)
6252 : detail::undirected_edge_key(u, v));
6253 }
6254
6255 while (static_cast<int>(edges.size()) < m_) {
6256 std::pair<int, int> edge;
6257 if (!detail::try_generate_distinct(seen, [&] {
6258 edge = detail::get_random_graph_edge(n_, is_directed_,
6259 has_self_loops_);
6260 if (!is_directed_ and edge.first > edge.second)
6261 std::swap(edge.first, edge.second);
6262 return is_directed_ ? detail::directed_edge_key(edge.first,
6263 edge.second)
6264 : detail::undirected_edge_key(
6265 edge.first, edge.second);
6266 }))
6267 throw detail::error("wgraph: not enough edges to generate");
6268 edges.emplace_back(edge);
6269 }
6270
6271 return value(n_, edges, is_directed_);
6272 }
6273};
6274
6275// Implementation of wtree::value constructor from wgraph.
6276// O(n + m alpha(n)).
6277template <typename VWeight, typename EWeight>
6278wtree<VWeight, EWeight>::value::value(
6279 const typename wgraph<VWeight, EWeight>::value &g)
6280 : n_(g.n()), adj_(g.n()), add_1_(false), print_n_(false), dsu_(g.n()) {
6281 tgen_ensure(g.n() > 0, "wtree: value: graph must have at least one vertex");
6282 tgen_ensure(!g.is_directed(),
6283 "wtree: value: graph must be undirected to form a tree");
6284
6285 if (g.vertex_weights().has_value())
6286 vertex_weights_ = *g.vertex_weights();
6287 if (g.edge_weights().has_value())
6288 edge_weights_ = std::vector<EWeight>();
6289
6290 if (n_ == 1)
6291 return;
6292
6293 std::vector<int> order(g.m());
6294 std::iota(order.begin(), order.end(), 0);
6295 tgen::shuffle(order.begin(), order.end());
6296
6297 std::vector<std::pair<int, int>> tree_edges;
6298 tree_edges.reserve(n_ - 1);
6299
6300 for (int i : order) {
6301 auto [u, v] = g.edges()[i];
6302 if (!dsu_.unite(u, v))
6303 continue;
6304 if (u > v)
6305 std::swap(u, v);
6306
6307 tree_edges.emplace_back(u, v);
6308 adj_[u].insert(v);
6309 adj_[v].insert(u);
6310 if (edge_weights_.has_value())
6311 edge_weights_->push_back((*g.edge_weights())[i]);
6312 if (static_cast<int>(tree_edges.size()) == n_ - 1)
6313 break;
6314 }
6315
6316 tgen_ensure(static_cast<int>(tree_edges.size()) == n_ - 1,
6317 "wtree: value: graph must be connected to form a tree");
6318
6319 edges_ = std::move(tree_edges);
6320}
6321
6322/*
6323 * Other types of weighted-ness.
6324 */
6325
6326// Vertex weighted graph.
6327template <typename VWeight> using vgraph = wgraph<VWeight, int>;
6328
6329// Edge weighted graph.
6330template <typename EWeight> using egraph = wgraph<int, EWeight>;
6331
6332// Unweighted graph.
6333using graph = wgraph<int, int>;
6334
6335/*
6336 * Standard graphs.
6337 */
6338
6339// Complete.
6340// O(n^2).
6341inline graph::value K(int n) { return graph(n, n * (n - 1) / 2).gen(); }
6342
6343// Path.
6344// Path with `n` vertices. The edges of the path are 0 and n-1.
6345// If directed, edges are i -> i+1 for i in [0, n-2).
6346// O(n).
6347inline graph::value P(int n, bool is_directed = false) {
6348 graph g(n, n - 1, is_directed);
6349 for (int i = 0; i + 1 < n; ++i)
6350 g.add_edge(i, i + 1);
6351 return g.gen();
6352}
6353
6354// Cycle.
6355// n >= 3.
6356// If directed, edges are i -> (i+1) % n.
6357// O(n).
6358inline graph::value C(int n, bool is_directed = false) {
6359 tgen_ensure(n >= 3, "graph: cycle size must be at least 3");
6360
6361 graph g(n, n, is_directed);
6362 for (int i = 0; i < n; ++i)
6363 g.add_edge(i, (i + 1) % n);
6364 return g.gen();
6365}
6366
6367// Complete bipartite.
6368// The first side has vertices `0` to `n1-1`, the second side has vertices `n1`
6369// to `n1+n2-1`.
6370// O(n1 * n2).
6371inline graph::value K(int n1, int n2) {
6372 graph g(n1 + n2, static_cast<long long>(n1) * n2);
6373 for (int i = 0; i < n1; ++i)
6374 for (int j = 0; j < n2; ++j)
6375 g.add_edge(i, n1 + j);
6376 return g.gen();
6377}
6378
6379// Star.
6380// The center is vertex 0.
6381// O(n).
6382inline graph::value S(int n) { return K(1, n - 1); }
6383
6384/****************
6385 * *
6386 * GEOMETRY *
6387 * *
6388 ****************/
6389
6390namespace geometry {
6391
6392// Point on the plane with coordinates of type T.
6393template <typename T> struct point {
6394 static_assert(std::is_arithmetic_v<T>,
6395 "point requires an arithmetic coordinate type");
6396
6397 // Dot/cross product type: __int128 for T = long long, long long for other
6398 // integral T, T for floating-point.
6399 using product_t = std::conditional_t<
6400 std::is_same_v<T, long long>, detail::i128,
6401 std::conditional_t<std::is_integral_v<T>, long long, T>>;
6402
6403 // x and y coordinates.
6404 T x_, y_;
6405
6406 // Constructs a point with coordinates x and y.
6407 point(T x = 0, T y = 0) : x_(x), y_(y) {}
6408
6409 // Returns the x coordinate.
6410 T x() const { return x_; }
6411
6412 // Returns the y coordinate.
6413 T y() const { return y_; }
6414
6415 // Equality of coordinates, with epsilon-based equality for floating-point
6416 // coordinates (tolerance 1e-9).
6417 static bool coord_eq(T a, T b) {
6418 if constexpr (std::is_integral_v<T>)
6419 return a == b;
6420 constexpr T eps = T(1e-9);
6421 T d = a - b;
6422 return d >= -eps and d <= eps;
6423 }
6424
6425 // Lexicographic order (by x, then y).
6426 bool operator<(const point &p) const {
6427 if (!coord_eq(x_, p.x()))
6428 return x_ < p.x();
6429 return y_ < p.y();
6430 }
6431
6432 // Equality of coordinates.
6433 bool operator==(const point &p) const {
6434 return coord_eq(x_, p.x()) and coord_eq(y_, p.y());
6435 }
6436
6437 // Vector addition.
6438 point operator+(const point &p) const {
6439 return point(x_ + p.x(), y_ + p.y());
6440 }
6441
6442 // Vector subtraction.
6443 point operator-(const point &p) const {
6444 return point(x_ - p.x(), y_ - p.y());
6445 }
6446
6447 // Scalar multiplication.
6448 point operator*(T c) const { return point(x_ * c, y_ * c); }
6449
6450 // Dot product.
6451 product_t operator*(const point &p) const {
6452 if constexpr (std::is_floating_point_v<T>)
6453 return x_ * p.x() + y_ * p.y();
6454 return product_t(x_) * p.x() + product_t(y_) * p.y();
6455 }
6456
6457 // Cross product (signed area of the parallelogram).
6458 product_t operator^(const point &p) const {
6459 if constexpr (std::is_floating_point_v<T>)
6460 return x_ * p.y() - y_ * p.x();
6461 return product_t(x_) * p.y() - product_t(y_) * p.x();
6462 }
6463
6464 // Prints the point as "x y".
6465 friend std::ostream &operator<<(std::ostream &out, const point &p) {
6466 return out << p.x() << ' ' << p.y();
6467 }
6468};
6469
6470// Generates n distinct integer points in [min_coord, max_coord]^2 with no three
6471// collinear.
6472// O(n).
6473inline std::vector<point<long long>>
6474random_points_general_position(int n, long long min_coord,
6475 long long max_coord) {
6476 tgen_ensure(n > 0,
6477 "geometry: random_points_general_position: n must be positive");
6478 tgen_ensure(max_coord >= min_coord,
6479 "geometry: random_points_general_position: min_coord must be "
6480 "at most max_coord");
6482 static_cast<detail::i128>(max_coord) - min_coord <=
6483 std::numeric_limits<long long>::max(),
6484 "geometry: random_points_general_position: coordinate range too large");
6485 uint64_t width = max_coord - min_coord;
6486 uint64_t p = math::prime_from(2 * n);
6487
6488 // Requires width >= p - 1 because sheared coordinates lie in [0, p - 1].
6489 tgen_ensure(width >= p - 1,
6490 "geometry: random_points_general_position: coordinate range "
6491 "too small for n");
6492
6493 // Base set: (x, x^-1 mod p) for x = 1, ..., p - 1.
6494 //
6495 // For a line ax + by + c = 0, substituting y = x^-1 gives ax^2 + cx + b = 0
6496 // (for x != 0), a quadratic with at most two roots in F_p. So at most two
6497 // base points lie on any line. x |-> x^-1 is bijective on {1, ..., p - 1},
6498 // so all points are distinct and no three are collinear.
6499 std::vector<uint64_t> x_range(p - 1);
6500 std::iota(x_range.begin(), x_range.end(), 1);
6501 shuffle(x_range.begin(), x_range.end());
6502 std::vector<detail::i128> bx(n), by(n);
6503 for (int i = 0; i < n; ++i) {
6504 uint64_t x = x_range[i];
6505 bx[i] = x;
6506 by[i] = math::modular_inverse(x, p);
6507 }
6508
6509 // Randomize placement without breaking general position: compose elementary
6510 // shears in SL(2, F_p), each either [1 r; 0 1] or [1 0; r 1] with
6511 // r in {-2, -1, 1, 2} (mod p). Every shear has determinant 1, so their
6512 // product is invertible. Invertible linear maps preserve collinearity, so
6513 // the image still has no three collinear points.
6514 const int num_shears = 8;
6515 std::vector<detail::i128> lin_x = bx, lin_y = by;
6516
6517 for (int it = 0; it < num_shears; ++it) {
6518 bool vertical_shear = next(2) == 0;
6519 int shear_r = pick({-2, -1, 1, 2});
6520
6521 for (int i = 0; i < n; ++i) {
6522 if (vertical_shear)
6523 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;
6524 else
6525 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;
6526
6527 if (lin_x[i] < 0)
6528 lin_x[i] += p;
6529 if (lin_y[i] < 0)
6530 lin_y[i] += p;
6531 }
6532 }
6533
6534 detail::i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0],
6535 max_y = lin_y[0];
6536 for (int i = 1; i < n; ++i) {
6537 min_x = std::min(min_x, lin_x[i]);
6538 max_x = std::max(max_x, lin_x[i]);
6539 min_y = std::min(min_y, lin_y[i]);
6540 max_y = std::max(max_y, lin_y[i]);
6541 }
6542
6543 long long x_shift =
6544 min_coord - min_x + next<long long>(0, width - (max_x - min_x));
6545 long long y_shift =
6546 min_coord - min_y + next<long long>(0, width - (max_y - min_y));
6547
6548 std::vector<point<long long>> pts;
6549 for (int i = 0; i < n; ++i)
6550 pts.emplace_back(lin_x[i] + x_shift, lin_y[i] + y_shift);
6551 return pts;
6552}
6553
6554namespace detail {
6555
6556using i128 = tgen::detail::i128;
6557
6558// Signed area of triangle (a, b, p); positive iff (a, b, p) are in
6559// counterclockwise order. 0 iff (a, b, p) are collinear. O(1).
6560inline i128 ccw(const point<long long> &a, const point<long long> &b,
6561 const point<long long> &p) {
6562 return (static_cast<i128>(b.x()) - a.x()) *
6563 (static_cast<i128>(p.y()) - a.y()) -
6564 (static_cast<i128>(b.y()) - a.y()) *
6565 (static_cast<i128>(p.x()) - a.x());
6566}
6567
6568// Integer projection of P onto line AB (A and B need not be distinct).
6569inline i128 proj_on_ab(const point<long long> &P, const point<long long> &A,
6570 const point<long long> &B) {
6571 return (P - A) * (B - A);
6572}
6573
6574// In-place Hamiltonian path on points[left..right-1] with points[left]
6575// start and points[right-1] end.
6576// O(n log n) expected if points are "random", O(n^2) worst case.
6577inline void conquer(std::vector<point<long long>> &points, int left,
6578 int right) {
6579 if (right - left <= 3)
6580 return;
6581
6582 point<long long> A = points[left], B = points[right - 1];
6583
6584 // If all points are collinear, sort them properly and return.
6585 bool all_collinear = true;
6586 for (int k = left + 1; k < right - 1; ++k) {
6587 if (ccw(A, B, points[k]) != 0) {
6588 all_collinear = false;
6589 break;
6590 }
6591 }
6592 if (all_collinear) {
6593 std::sort(points.begin() + left, points.begin() + right,
6594 [&](const point<long long> &P, const point<long long> &Q) {
6595 return proj_on_ab(P, A, B) < proj_on_ab(Q, A, B);
6596 });
6597 return;
6598 }
6599
6600 // Choses a pivot that is not collinear with A and B.
6601 std::vector<int> candidates;
6602 for (int k = left + 1; k < right - 1; ++k) {
6603 if (ccw(A, B, points[k]) != 0)
6604 candidates.push_back(k);
6605 }
6606 int ci = candidates[next(0, static_cast<int>(candidates.size()) - 1)];
6607 point<long long> C = points[ci];
6608
6609 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6610 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6611 bool a_on_positive = ccw(C, A, B) < 0;
6612
6613 // Classify interior points into two sides of the wedge A-C-B for partition.
6614 // Collinear points on AB are tie-broken along the segment.
6615 i128 proj_sum = proj_on_ab(A, A, B) + proj_on_ab(B, A, B);
6616 auto is_positive = [&](const point<long long> &P) -> bool {
6617 i128 s = wa * ccw(C, A, P) + wb * ccw(C, B, P);
6618 // Weighted wedge side of P w.r.t. C, A, B.
6619 if (s != 0)
6620 return s > 0;
6621 // P is on line AB: split by projection past the midpoint.
6622 return 2 * proj_on_ab(P, A, B) > proj_sum;
6623 };
6624
6625 // Holds C at points[right-2] while classifying interior points in
6626 // [left+1, right-3].
6627 if (ci != right - 2)
6628 std::swap(points[ci], points[right - 2]);
6629
6630 int i = left + 1;
6631 int j = right - 3;
6632 while (i < j) {
6633 if (is_positive(points[i]) == a_on_positive)
6634 ++i;
6635 else if (is_positive(points[j]) != a_on_positive)
6636 --j;
6637 else {
6638 std::swap(points[i], points[j]);
6639 ++i;
6640 --j;
6641 }
6642 }
6643
6644 // After partition:
6645 // points[left]=A | (A,C)... | C | (C,B)... | points[right-1]=B.
6646
6647 // After the swap, p is the index of C (pivot between the two subpaths).
6648 int p = i;
6649 if (i == j and is_positive(points[i]) == a_on_positive)
6650 ++p;
6651 std::swap(points[p], points[right - 2]);
6652
6653 // Path A -> C.
6654 conquer(points, left, p + 1);
6655 // Path C -> B.
6656 conquer(points, p, right);
6657}
6658
6659// Samples k sorted distinct integers from [left, right] uniformly.
6660// Optimized for performance (pool partial Fisher–Yates or complement path for
6661// modest ranges; sparse-map fallback otherwise).
6662// O(k log k); O(right - left) memory when the range is modest.
6663inline std::vector<long long>
6664sample_sorted_distinct_in_range(int k, long long left, long long right) {
6665 long long universe = right - left + 1;
6666 std::vector<long long> res;
6667 res.reserve(k);
6668 if (k == 0)
6669 return res;
6670
6671 constexpr long long pool_threshold = 8'000'000;
6672 constexpr long long pool_always_below = 500'000;
6673
6674 if (universe <= pool_threshold and
6675 (universe <= pool_always_below or k >= universe / 4)) {
6676 size_t u = universe;
6677 size_t ks = k;
6678 std::vector<long long> pool(u);
6679 std::iota(pool.begin(), pool.end(), left);
6680 size_t m = ks <= u / 2 ? ks : u - ks;
6681 for (size_t i = 0; i < m; ++i) {
6682 size_t j = next<size_t>(i, u - 1);
6683 std::swap(pool[i], pool[j]);
6684 }
6685 if (ks <= u / 2) {
6686 res.assign(pool.begin(), pool.begin() + ks);
6687 std::sort(res.begin(), res.end());
6688 } else {
6689 std::vector<char> excluded(u, 0);
6690 for (size_t i = 0; i < m; ++i)
6691 excluded[pool[i] - left] = 1;
6692 for (long long v = left; v <= right; ++v)
6693 if (!excluded[v - left])
6694 res.push_back(v);
6695 }
6696 } else {
6697 std::unordered_map<long long, long long> virtual_list;
6698 virtual_list.reserve(k * 2);
6699 for (long long i = 0; i < k; ++i) {
6700 long long j = next<long long>(i, universe - 1);
6701 long long vi = virtual_list.count(i) ? virtual_list[i] : i;
6702 long long vj = virtual_list.count(j) ? virtual_list[j] : j;
6703 virtual_list[j] = vi;
6704 virtual_list[i] = vj;
6705 res.push_back(virtual_list[i] + left);
6706 }
6707 std::sort(res.begin(), res.end());
6708 }
6709 return res;
6710}
6711
6712// Valtr-style signed edge components along one axis from n sorted distinct
6713// coordinates. The n differences sum to zero.
6714inline std::vector<long long>
6715valtr_edge_components(const std::vector<long long> &sorted_coords) {
6716 int n = sorted_coords.size();
6717 std::vector<long long> left, right;
6718 left.reserve(n / 2);
6719 right.reserve(n / 2);
6720 for (int i = 1; i + 1 < n; ++i) {
6721 if (next(2) == 0)
6722 left.push_back(sorted_coords[i]);
6723 else
6724 right.push_back(sorted_coords[i]);
6725 }
6726 long long lo = sorted_coords.front(), hi = sorted_coords.back();
6727 std::vector<long long> seq;
6728 seq.reserve(n + 1);
6729 seq.push_back(lo);
6730 for (long long v : left)
6731 seq.push_back(v);
6732 seq.push_back(hi);
6733 for (auto it = right.rbegin(); it != right.rend(); ++it)
6734 seq.push_back(*it);
6735 seq.push_back(lo);
6736 std::vector<long long> comps(n);
6737 for (int i = 0; i < n; ++i)
6738 comps[i] = seq[i + 1] - seq[i];
6739 return comps;
6740}
6741
6742// Drops boundary vertices that are collinear with their cyclic neighbors.
6743// O(m), m = |points|.
6744inline std::vector<point<long long>>
6745simplify_strict_boundary(std::vector<point<long long>> points) {
6746 int n = points.size();
6747 if (n < 3)
6748 return points;
6749
6750 std::vector<point<long long>> strict_points;
6751 strict_points.reserve(n);
6752 for (int i = 0; i < n; ++i) {
6753 if (ccw(points[(i + n - 1) % n], points[i], points[(i + 1) % n]) != 0)
6754 strict_points.push_back(points[i]);
6755 }
6756 return strict_points;
6757}
6758
6759// Picks k evenly spaced vertices along a longer cyclic boundary.
6760// O(k).
6761inline std::vector<point<long long>>
6762subsample_boundary(const std::vector<point<long long>> &points, int k) {
6763 int n = points.size();
6764 if (n <= k)
6765 return points;
6766
6767 std::vector<point<long long>> sampled_points;
6768 sampled_points.reserve(k);
6769 for (int i = 0; i < k; ++i)
6770 sampled_points.push_back(points[(static_cast<i128>(i) * n) / k]);
6771 return sampled_points;
6772}
6773
6774// Random translation so the polygon lies in the box.
6775// O(|points|).
6776inline void place_inside_box(std::vector<point<long long>> &points,
6777 long long min_coord, long long max_coord) {
6778 long long width = max_coord - min_coord + 1;
6779
6780 i128 min_x = points[0].x(), max_x = points[0].x();
6781 i128 min_y = points[0].y(), max_y = points[0].y();
6782 for (const point<long long> &p : points) {
6783 min_x = std::min(min_x, static_cast<i128>(p.x()));
6784 max_x = std::max(max_x, static_cast<i128>(p.x()));
6785 min_y = std::min(min_y, static_cast<i128>(p.y()));
6786 max_y = std::max(max_y, static_cast<i128>(p.y()));
6787 }
6788
6789 i128 span_x = max_x - min_x;
6790 i128 span_y = max_y - min_y;
6791 // Random slack keeps the polygon inside the box without filling it.
6792 i128 shift_x =
6793 min_coord - min_x +
6794 next<long long>(0, width - 1 - static_cast<long long>(span_x));
6795 i128 shift_y =
6796 min_coord - min_y +
6797 next<long long>(0, width - 1 - static_cast<long long>(span_y));
6798
6799 for (point<long long> &p : points)
6800 p = point<long long>(p.x() + shift_x, p.y() + shift_y);
6801}
6802
6803// Random cyclic shift.
6804// O(|points|).
6805inline void randomize_cyclic_shift(std::vector<point<long long>> &points) {
6806 int rot = next(points.size());
6807 if (rot > 0)
6808 std::rotate(points.begin(), points.begin() + rot, points.end());
6809}
6810
6811// Valtr walk for m edges; bbox minimum translated to the origin.
6812// O(m log m).
6813inline std::vector<point<long long>>
6814valtr_vertices(int m, const std::vector<long long> &x_comp,
6815 std::vector<long long> y_comp) {
6816 shuffle(y_comp.begin(), y_comp.end());
6817
6818 std::vector<point<long long>> edges(m);
6819 // Upper half-plane (positive y, or y = 0 and x > 0) sorts before lower.
6820 auto upper = [](const point<long long> &p) {
6821 return p.y() > 0 or (p.y() == 0 and p.x() > 0);
6822 };
6823 for (int i = 0; i < m; ++i)
6824 edges[i] = point<long long>(x_comp[i], y_comp[i]);
6825
6826 std::sort(edges.begin(), edges.end(),
6827 [&upper](const point<long long> &a, const point<long long> &b) {
6828 bool au = upper(a), bu = upper(b);
6829 if (au != bu)
6830 return au;
6831 auto cross = a ^ b;
6832 if (cross != 0)
6833 return cross > 0;
6834 return (a * a) < (b * b);
6835 });
6836
6837 // Prefix-sum the sorted edge vectors to obtain vertex coordinates.
6838 i128 cur_x = 0, cur_y = 0;
6839 std::vector<i128> px(m), py(m);
6840 for (int i = 0; i < m; ++i) {
6841 px[i] = cur_x;
6842 py[i] = cur_y;
6843 cur_x += edges[i].x();
6844 cur_y += edges[i].y();
6845 }
6846 tgen::detail::tgen_ensure_against_bug(
6847 cur_x == 0 and cur_y == 0,
6848 "geometry: random_convex_polygon: walk did not close");
6849
6850 i128 min_x = px[0], min_y = py[0];
6851 for (int i = 1; i < m; ++i) {
6852 min_x = std::min(min_x, px[i]);
6853 min_y = std::min(min_y, py[i]);
6854 }
6855
6856 // Shift so the bbox minimum is at the origin.
6857 std::vector<point<long long>> points;
6858 points.reserve(m);
6859 for (int i = 0; i < m; ++i)
6860 points.emplace_back(px[i] - min_x, py[i] - min_y);
6861 return points;
6862}
6863
6864} // namespace detail
6865
6866// Generates n vertices of a convex integer polygon inside a box.
6867// If strict is true, boundary vertices are guaranteed non-collinear when
6868// generation succeeds; retry count depends on n and width.
6869// Always returns points in counterclockwise order.
6870// O(n log n).
6871inline std::vector<point<long long>>
6872random_convex_polygon(int n, long long min_coord, long long max_coord,
6873 bool strict = false) {
6874 tgen_ensure(n >= 3,
6875 "geometry: random_convex_polygon: n must be at least 3");
6876 tgen_ensure(max_coord >= min_coord,
6877 "geometry: random_convex_polygon: min_coord must be at most "
6878 "max_coord");
6879 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord + 1 <=
6880 std::numeric_limits<long long>::max(),
6881 "geometry: random_convex_polygon: coordinate range too large");
6882 long long width = max_coord - min_coord + 1;
6884 width >= n,
6885 "geometry: random_convex_polygon: coordinate range too small for n");
6886
6887 // Valtr walk size: n in weak mode; strict mode uses a larger grid so
6888 // collinear removal still leaves at least n vertices to subsample.
6889 int num_coords = n;
6890 if (strict) {
6891 // Extra grid lines beyond n: at least 100 (small-n headroom), about
6892 // n/1000 for large n, and never more than width - n.
6893 int extra = width <= n ? 0
6894 : std::min<long long>(std::max(100, n / 1000),
6895 width - n);
6896 num_coords = n + extra;
6897 }
6898
6899 // Strict mode retries coordinate sampling when simplification leaves < n
6900 // vertices; weak mode has no failure path, so one attempt always suffices.
6901 const int max_attempts = strict ? 32 : 1;
6902 for (int i = 0; i < max_attempts; ++i) {
6903 // Build a convex lattice polygon on [0, width - 1]^2, then translate.
6904 std::vector<long long> x_sorted =
6905 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6906 std::vector<long long> y_sorted =
6907 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6908 std::vector<long long> x_comp = detail::valtr_edge_components(x_sorted);
6909 std::vector<long long> y_comp = detail::valtr_edge_components(y_sorted);
6910
6911 std::vector<point<long long>> points =
6912 detail::valtr_vertices(num_coords, x_comp, std::move(y_comp));
6913
6914 if (strict) {
6915 std::vector<point<long long>> simplified =
6916 detail::simplify_strict_boundary(std::move(points));
6917 // Tight boxes can leave too few vertices -> resample coordinates.
6918 if (static_cast<int>(simplified.size()) < n)
6919 continue;
6920
6921 points = detail::subsample_boundary(simplified, n);
6922 }
6923
6924 detail::place_inside_box(points, min_coord, max_coord);
6925 detail::randomize_cyclic_shift(points);
6926 return points;
6927 }
6928
6929 // Generation failed.
6930 throw tgen::detail::error(
6931 "geometry: random_convex_polygon: generation failed: coordinate "
6932 "range too small for n");
6933}
6934
6935// Random simple polygon through given distinct points.
6936// Collinear triples are allowed; fails if all points are collinear.
6937// Always returns vertices in counterclockwise order.
6938// O(n log n) expected if points are "random", O(n^2) worst case.
6940 const std::vector<point<long long>> &points) {
6941 int n = points.size();
6942 tgen_ensure(n >= 3,
6943 "geometry: random_simple_polygon_through_points: need at "
6944 "least 3 points");
6946 static_cast<int>(
6947 std::set<point<long long>>(points.begin(), points.end()).size()) ==
6948 n,
6949 "geometry: random_simple_polygon_through_points: points must "
6950 "be distinct");
6951
6952 int idx_a = 0, idx_b = 0;
6953 for (int i = 1; i < n; ++i) {
6954 if (points[i] < points[idx_a])
6955 idx_a = i;
6956 if (points[idx_b] < points[i])
6957 idx_b = i;
6958 }
6959 point<long long> A = points[idx_a], B = points[idx_b];
6960
6961 bool all_collinear = true;
6962 for (int i = 0; i < n; ++i) {
6963 if (i == idx_a or i == idx_b)
6964 continue;
6965 if (detail::ccw(A, B, points[i]) != 0) {
6966 all_collinear = false;
6967 break;
6968 }
6969 }
6970 tgen_ensure(!all_collinear,
6971 "geometry: random_simple_polygon_through_points: all points "
6972 "are collinear; no simple polygon exists");
6973
6974 std::vector<point<long long>> chain;
6975 chain.push_back(A);
6976 int left_count = 0;
6977 for (int i = 0; i < n; ++i) {
6978 if (i == idx_a or i == idx_b)
6979 continue;
6980 if (detail::ccw(A, B, points[i]) <= 0) {
6981 chain.push_back(points[i]);
6982 ++left_count;
6983 }
6984 }
6985 chain.push_back(B);
6986 for (int i = 0; i < n; ++i) {
6987 if (i == idx_a or i == idx_b)
6988 continue;
6989 if (detail::ccw(A, B, points[i]) > 0)
6990 chain.push_back(points[i]);
6991 }
6992 chain.push_back(A);
6993
6994 int n1 = 2 + left_count;
6995 // Upper chain: A -> B.
6996 detail::conquer(chain, 0, n1);
6997 // Lower chain: B -> A.
6998 detail::conquer(chain, n1 - 1, chain.size());
6999
7000 // Cyclic vertex order: chain[1..n1) then chain[n1..end) (skip each path's
7001 // start vertex).
7002 std::vector<point<long long>> poly;
7003 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);
7004 poly.insert(poly.end(), chain.begin() + n1, chain.end());
7005 return poly;
7006}
7007
7008namespace detail {
7009
7010// Samples n distinct integer points in [min_coord, max_coord]^2.
7011// O(n log n).
7012inline std::vector<point<long long>>
7013random_distinct_points_in_box(int n, long long min_coord, long long max_coord) {
7014 long long width = max_coord - min_coord;
7015 i128 side_128 = width + 1;
7016 i128 universe = side_128 * side_128;
7017 tgen_ensure(universe <= std::numeric_limits<long long>::max(),
7018 "geometry: random_simple_polygon: coordinate range too large");
7019 long long side = side_128;
7020 tgen_ensure(universe >= n,
7021 "geometry: random_simple_polygon: coordinate range too small "
7022 "for n distinct points");
7023
7024 // Decodes a linear grid key (x * side + y) to a point.
7025 auto decode = [&](long long key) -> point<long long> {
7026 return point<long long>(min_coord + key / side, min_coord + key % side);
7027 };
7028
7029 // Repeats until all generated points are not collinear.
7030 // Runs O(1) expected times.
7031 while (true) {
7032 std::vector<long long> keys =
7033 distinct_range<long long>(0, universe - 1).gen_list(n).to_std();
7034
7035 std::vector<point<long long>> points;
7036 points.reserve(n);
7037 for (long long key : keys)
7038 points.push_back(decode(key));
7039
7040 // Checks if the points are not all collinear.
7041 for (int i = 2; i < n; ++i) {
7042 if (ccw(points[0], points[1], points[i]) != 0)
7043 return points;
7044 }
7045 }
7046}
7047
7048// Axis-aligned edge data for a CCW polygon (interior on the left).
7049// O(1).
7050struct ortho_poly_edge {
7051 long long len;
7052 bool horiz;
7053 long long fixed;
7054 long long lo, hi;
7055 int out_x, out_y;
7056};
7057
7058// True if a, b, c lie on one horizontal or vertical line.
7059// O(1).
7060inline bool ortho_axis_collinear(const point<long long> &a,
7061 const point<long long> &b,
7062 const point<long long> &c) {
7063 return (a.x() == b.x() and b.x() == c.x()) or
7064 (a.y() == b.y() and b.y() == c.y());
7065}
7066
7067// Edge i of poly: orientation, span, exterior normal.
7068// O(1).
7069inline ortho_poly_edge
7070ortho_analyze_edge(const std::vector<point<long long>> &poly, int i) {
7071 int m = poly.size();
7072 point<long long> a = poly[i], b = poly[(i + 1) % m];
7073 ortho_poly_edge e{};
7074 if (a.y() == b.y()) {
7075 e.horiz = true;
7076 e.fixed = a.y();
7077 e.lo = std::min(a.x(), b.x());
7078 e.hi = std::max(a.x(), b.x());
7079 e.out_x = 0;
7080 e.out_y = a.x() < b.x() ? -1 : 1;
7081 } else {
7082 e.fixed = a.x();
7083 e.lo = std::min(a.y(), b.y());
7084 e.hi = std::max(a.y(), b.y());
7085 e.out_x = a.y() < b.y() ? 1 : -1;
7086 }
7087 e.len = e.hi - e.lo;
7088 return e;
7089}
7090
7091// True if open axis-aligned segments (a, b) and (c, d) properly cross or
7092// overlap (excluding shared endpoints).
7093// O(1).
7094inline bool ortho_open_seg_cross(const point<long long> &a,
7095 const point<long long> &b,
7096 const point<long long> &c,
7097 const point<long long> &d) {
7098 if (a.y() == b.y() and c.y() == d.y()) {
7099 if (a.y() != c.y())
7100 return false;
7101 long long lo1 = std::min(a.x(), b.x()), hi1 = std::max(a.x(), b.x());
7102 long long lo2 = std::min(c.x(), d.x()), hi2 = std::max(c.x(), d.x());
7103 return lo1 < hi2 and lo2 < hi1;
7104 }
7105 if (a.x() == b.x() and c.x() == d.x()) {
7106 if (a.x() != c.x())
7107 return false;
7108 long long lo1 = std::min(a.y(), b.y()), hi1 = std::max(a.y(), b.y());
7109 long long lo2 = std::min(c.y(), d.y()), hi2 = std::max(c.y(), d.y());
7110 return lo1 < hi2 and lo2 < hi1;
7111 }
7112 if (a.y() == b.y() and c.x() == d.x()) {
7113 long long hx = a.y(), vx = c.x();
7114 long long hlo = std::min(a.x(), b.x()), hhi = std::max(a.x(), b.x());
7115 long long vlo = std::min(c.y(), d.y()), vhi = std::max(c.y(), d.y());
7116 return hlo < vx and vx < hhi and vlo < hx and hx < vhi;
7117 }
7118 if (a.x() == b.x() and c.y() == d.y()) {
7119 long long vx = a.x(), hy = c.y();
7120 long long vlo = std::min(a.y(), b.y()), vhi = std::max(a.y(), b.y());
7121 long long hlo = std::min(c.x(), d.x()), hhi = std::max(c.x(), d.x());
7122 return vlo < hy and hy < vhi and hlo < vx and vx < hhi;
7123 }
7124 return false;
7125}
7126
7127// Integral ray-crossing point-in-polygon.
7128// O(|poly|).
7129inline bool ortho_point_inside(const std::vector<point<long long>> &poly,
7130 point<long long> p) {
7131 int m = poly.size();
7132 bool inside = false;
7133 for (int i = 0, j = m - 1; i < m; j = i++) {
7134 point<long long> a = poly[i], b = poly[j];
7135 if ((a.y() > p.y()) != (b.y() > p.y())) {
7136 i128 x_cross = i128(b.x() - a.x()) * (p.y() - a.y()) -
7137 i128(p.x() - a.x()) * (b.y() - a.y());
7138 if ((a.y() < b.y()) ? x_cross > 0 : x_cross < 0)
7139 inside = !inside;
7140 }
7141 }
7142 return inside;
7143}
7144
7145// True if open segment s0-s1 hits any poly edge except edge_i.
7146// O(|poly|).
7147inline bool ortho_seg_hits_boundary(const std::vector<point<long long>> &poly,
7148 int edge_i, point<long long> s0,
7149 point<long long> s1) {
7150 int m = poly.size();
7151 for (int j = 0; j < m; ++j) {
7152 if (j == edge_i)
7153 continue;
7154 if (ortho_open_seg_cross(s0, s1, poly[j], poly[(j + 1) % m]))
7155 return true;
7156 }
7157 return false;
7158}
7159
7160// True if splicing add between A and B on edge_i is valid: no vertex of add
7161// coincides with poly, new segments do not cross other boundary edges, and
7162// inward notches keep all of add inside poly.
7163// O(|poly|).
7164inline bool ortho_bump_valid(const std::vector<point<long long>> &poly,
7165 point<long long> A, point<long long> B,
7166 const std::vector<point<long long>> &add,
7167 int edge_i, bool inward) {
7168 // Checks for duplicate vertices.
7169 for (point<long long> v : add) {
7170 for (point<long long> q : poly)
7171 if (v == q)
7172 return false;
7173 }
7174
7175 // Checks for new segment crossings.
7176 point<long long> prev = A;
7177 for (point<long long> v : add) {
7178 if (ortho_seg_hits_boundary(poly, edge_i, prev, v))
7179 return false;
7180 prev = v;
7181 }
7182 if (ortho_seg_hits_boundary(poly, edge_i, prev, B))
7183 return false;
7184
7185 // Inward cuts: crossing checks alone miss notches that extend past the
7186 // interior.
7187 if (inward) {
7188 for (point<long long> v : add)
7189 if (!ortho_point_inside(poly, v))
7190 return false;
7191 }
7192
7193 return true;
7194}
7195
7196// Splices a rectangular tab or notch on edge edge_i over [lo, hi], extending
7197// depth units perpendicular to the edge.
7198// O(|poly|).
7199inline bool ortho_bump_edge(std::vector<point<long long>> &poly, int edge_i,
7200 const ortho_poly_edge &e, long long lo,
7201 long long hi, long long depth, bool inward) {
7202 int m = poly.size();
7203 point<long long> A = poly[edge_i], B = poly[(edge_i + 1) % m];
7204
7205 int step_x = inward ? -e.out_x : e.out_x;
7206 int step_y = inward ? -e.out_y : e.out_y;
7207
7208 std::vector<point<long long>> add;
7209 if (e.horiz) {
7210 long long y = e.fixed, y2 = y + step_y * depth;
7211 if (A.x() < B.x()) {
7212 if (lo > A.x())
7213 add.emplace_back(lo, y);
7214 add.emplace_back(lo, y2);
7215 add.emplace_back(hi, y2);
7216 if (hi < B.x())
7217 add.emplace_back(hi, y);
7218 } else {
7219 if (hi < A.x())
7220 add.emplace_back(hi, y);
7221 add.emplace_back(hi, y2);
7222 add.emplace_back(lo, y2);
7223 if (lo > B.x())
7224 add.emplace_back(lo, y);
7225 }
7226 } else {
7227 long long x = e.fixed, x2 = x + step_x * depth;
7228 if (A.y() < B.y()) {
7229 if (lo > A.y())
7230 add.emplace_back(x, lo);
7231 add.emplace_back(x2, lo);
7232 add.emplace_back(x2, hi);
7233 if (hi < B.y())
7234 add.emplace_back(x, hi);
7235 } else {
7236 if (hi < A.y())
7237 add.emplace_back(x, hi);
7238 add.emplace_back(x2, hi);
7239 add.emplace_back(x2, lo);
7240 if (lo > B.y())
7241 add.emplace_back(x, lo);
7242 }
7243 }
7244 if (!ortho_bump_valid(poly, A, B, add, edge_i, inward))
7245 return false;
7246
7247 poly.insert(poly.begin() + edge_i + 1, add.begin(), add.end());
7248 return true;
7249}
7250
7251// Picks edge i with probability proportional to
7252// e.len * (4 + min(global_timestamp - last_used[i], 8)).
7253// O(|poly|).
7254inline int ortho_pick_poly_edge(const std::vector<point<long long>> &poly,
7255 std::vector<int> &last_used, int &time_stamp) {
7256 int m = poly.size();
7257 if (static_cast<int>(last_used.size()) != m) {
7258 last_used.assign(m, 0);
7259 time_stamp = 0;
7260 }
7261 int global_timestamp = time_stamp;
7262 std::vector<long long> weights(m);
7263 long long total = 0;
7264 for (int i = 0; i < m; ++i) {
7265 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7266 weights[i] = e.len * (4 + std::min(global_timestamp - last_used[i], 8));
7267 total += weights[i];
7268 }
7269 long long pick = next<long long>(0, total - 1);
7270 for (int i = 0; i < m; ++i) {
7271 pick -= weights[i];
7272 if (pick < 0) {
7273 last_used[i] = ++time_stamp;
7274 return i;
7275 }
7276 }
7277 last_used[m - 1] = ++time_stamp;
7278 return m - 1;
7279}
7280
7281// One random inflate/cut attempt.
7282// O(|poly|).
7283inline bool ortho_try_bump(std::vector<point<long long>> &poly, int n,
7284 std::vector<int> &last_used, int &time_stamp) {
7285 if (poly.size() < 3)
7286 return false;
7287
7288 int ei = ortho_pick_poly_edge(poly, last_used, time_stamp);
7289 ortho_poly_edge e = ortho_analyze_edge(poly, ei);
7290
7291 // Edge subdivision can leave length-1 segments; a tab needs span >= 2.
7292 if (e.len < 2)
7293 return false;
7294
7295 // Random subinterval [lo, lo + span] on the edge, with 2 <= span <= e.len.
7296 long long span = next<long long>(2, e.len);
7297 long long lo = next<long long>(e.lo, e.hi - span);
7298
7299 // max_depth: cap on perpendicular tab/notch height (~sqrt(n), in [2, 12]).
7300 // depth: actual height; shallow usually, up to max_depth 10% of the time.
7301 long long max_depth =
7302 std::clamp<long long>((long long)(std::sqrt(n)) / 2 + 2, 2LL, 12LL);
7303 long long depth =
7304 next(10) == 0 ? next<long long>(std::max(2LL, max_depth / 2), max_depth)
7305 : next<long long>(1, std::max(2LL, max_depth / 3));
7306
7307 // ~25% inward cuts; outward tabs succeed more often.
7308 constexpr int ortho_inward_prob_denom = 4;
7309 return ortho_bump_edge(poly, ei, e, lo, lo + span, depth,
7310 next(ortho_inward_prob_denom) == 0);
7311}
7312
7313// Drop axis-aligned collinear vertices.
7314// O(n).
7315inline std::vector<point<long long>>
7316ortho_simplify_collinear(std::vector<point<long long>> poly) {
7317 int n = poly.size();
7318 if (n < 3)
7319 return poly;
7320 std::vector<point<long long>> out;
7321 out.reserve(n);
7322 for (int i = 0; i < n; ++i) {
7323 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7324 poly[(i + 1) % n]))
7325 out.push_back(poly[i]);
7326 }
7327 return out.size() >= 3 ? out : poly;
7328}
7329
7330// Remove one collinear vertex.
7331// O(n).
7332inline bool ortho_remove_one_collinear(std::vector<point<long long>> &poly) {
7333 int n = poly.size();
7334 if (n < 4)
7335 return false;
7336 for (int i = 0; i < n; ++i) {
7337 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7338 poly[(i + 1) % n]))
7339 continue;
7340 poly.erase(poly.begin() + i);
7341 return true;
7342 }
7343 return false;
7344}
7345
7346// Insert collinear vertices on straight edges until size reaches `target` (or
7347// no edge has spare integer points). Preserves boundary order.
7348// O(|poly| + target).
7349inline void ortho_fill_collinear(std::vector<point<long long>> &poly,
7350 int target) {
7351 int need = target - static_cast<int>(poly.size());
7352 if (need <= 0)
7353 return;
7354
7355 std::vector<point<long long>> out;
7356 int m = static_cast<int>(poly.size());
7357 out.reserve(poly.size() + static_cast<size_t>(need));
7358
7359 for (int i = 0; i < m; ++i) {
7360 point<long long> a = poly[i], b = poly[(i + 1) % m];
7361 out.push_back(a);
7362 if (need <= 0)
7363 continue;
7364
7365 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7366 long long cap = e.len - 1;
7367 if (cap <= 0)
7368 continue;
7369
7370 // Adds `take` collinear vertices to the boundary.
7371 long long take = std::min<long long>(need, cap);
7372 bool forward = e.horiz ? a.x() < b.x() : a.y() < b.y();
7373 for (long long k = 0; k < take; ++k) {
7374 long long off = (k + 1) * (cap + 1) / (take + 1);
7375 long long coord = forward ? e.lo + off : e.hi - off;
7376 if (e.horiz)
7377 out.push_back({coord, e.fixed});
7378 else
7379 out.push_back({e.fixed, coord});
7380 }
7381 need -= take;
7382 }
7383 poly = std::move(out);
7384}
7385
7386// CCW square seed plus boundary inflate/cut to about n vertices.
7387// O(n^2) for small n; O(n) collinear fill dominates for large n.
7388inline std::vector<point<long long>> build_orthogonal_polygon(int n,
7389 bool strict) {
7390 // Seed square side: sqrt(n) for small n, ~n/4 for large n (collinear fill).
7391 long long side = std::max(3LL, static_cast<long long>(std::sqrt(n)));
7392 if (n > 1000)
7393 side = std::max(side, static_cast<long long>((n + 3) / 4));
7394 std::vector<point<long long>> poly = {
7395 {0, 0}, {side, 0}, {side, side}, {0, side}};
7396
7397 // Each successful bump adds 2 to 4 vertices.
7398 int target_ops = std::max(1, (n - 4) / 2);
7399
7400 // For large n, cap the number of operations to avoid quadratic complexity.
7401 if (n > 1000)
7402 target_ops = std::min(
7403 target_ops,
7404 400 + static_cast<int>(4 * std::sqrt(static_cast<double>(n))));
7405
7406 int failure_limit = std::min(target_ops * 8, 2000);
7407
7408 std::vector<int> last_used;
7409 int time_stamp = 0, consecutive_failures = 0;
7410 for (int ops = 0; ops < target_ops;) {
7411 // Stop early rather than overshoot n and trim.
7412 if (static_cast<int>(poly.size()) + 2 > n)
7413 break;
7414
7415 if (ortho_try_bump(poly, n, last_used, time_stamp)) {
7416 ++ops;
7417 consecutive_failures = 0;
7418 } else if (++consecutive_failures >= failure_limit) {
7419 // Stop bumping after many consecutive failures.
7420 break;
7421 }
7422 }
7423 if (strict)
7424 poly = ortho_simplify_collinear(std::move(poly));
7425
7426 // Bumps can overshoot n; drop collinear vertices until size <= n.
7427 while (static_cast<int>(poly.size()) > n and
7428 ortho_remove_one_collinear(poly))
7429 ;
7430
7431 if (!strict)
7432 ortho_fill_collinear(poly, n);
7433
7434 return poly;
7435}
7436
7437} // namespace detail
7438
7439// Random simple polygon.
7440// If strict, vertex set has no three collinear points
7441// (random_points_general_position); otherwise samples distinct grid points
7442// (collinear triples allowed), so it might be the case that (polygon[i],
7443// polygon[i+1], and polygon[i+2]) are collinear. Polygonizes via
7444// random_simple_polygon_through_points. Always counterclockwise.
7445// O(n log n) expected.
7446inline std::vector<point<long long>>
7447random_simple_polygon(int n, long long min_coord, long long max_coord,
7448 bool strict = false) {
7449 tgen_ensure(n >= 3,
7450 "geometry: random_simple_polygon: n must be at least 3");
7451 tgen_ensure(max_coord >= min_coord,
7452 "geometry: random_simple_polygon: min_coord must be at most "
7453 "max_coord");
7454 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord <=
7455 std::numeric_limits<long long>::max(),
7456 "geometry: random_simple_polygon: coordinate range too large");
7457
7458 std::vector<point<long long>> points =
7459 strict ? random_points_general_position(n, min_coord, max_coord)
7460 : detail::random_distinct_points_in_box(n, min_coord, max_coord);
7461 return random_simple_polygon_through_points(points);
7462}
7463
7464// Random orthogonal simple polygon, CCW.
7465// Exactly n vertices when !strict; at most n vertices when strict.
7466// O(n^2) for small n; O(n) for large n.
7467inline std::vector<point<long long>>
7468random_orthogonal_polygon(int n, long long min_coord, long long max_coord,
7469 bool strict = false) {
7470 tgen_ensure(n >= 4,
7471 "geometry: random_orthogonal_polygon: n must be at least 4");
7472 tgen_ensure(max_coord >= min_coord,
7473 "geometry: random_orthogonal_polygon: min_coord must be at "
7474 "most max_coord");
7475 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7476 std::numeric_limits<long long>::max(),
7477 "geometry: random_orthogonal_polygon: coordinate range too "
7478 "large");
7479 long long width = max_coord - min_coord + 1;
7480 tgen_ensure(width >= 4,
7481 "geometry: random_orthogonal_polygon: coordinate range too "
7482 "small");
7483
7484 std::vector<point<long long>> poly =
7485 detail::build_orthogonal_polygon(n, strict);
7486
7487 detail::i128 min_x = poly[0].x(), max_x = poly[0].x();
7488 detail::i128 min_y = poly[0].y(), max_y = poly[0].y();
7489 for (const point<long long> &p : poly) {
7490 min_x = std::min(min_x, static_cast<detail::i128>(p.x()));
7491 max_x = std::max(max_x, static_cast<detail::i128>(p.x()));
7492 min_y = std::min(min_y, static_cast<detail::i128>(p.y()));
7493 max_y = std::max(max_y, static_cast<detail::i128>(p.y()));
7494 }
7495 tgen_ensure(max_x - min_x < width and max_y - min_y < width,
7496 "geometry: random_orthogonal_polygon: coordinate range too "
7497 "small");
7498
7499 detail::place_inside_box(poly, min_coord, max_coord);
7500 detail::randomize_cyclic_shift(poly);
7501 return poly;
7502}
7503
7504} // namespace geometry
7505
7506/************
7507 * *
7508 * HACK *
7509 * *
7510 ************/
7511
7512namespace hack {
7513
7514namespace detail {
7515
7516using namespace tgen::detail;
7517
7518// Computes polynomial hash of a string.
7519// O(|s|).
7520inline int hash_string(const std::string &s, int base, int mod) {
7521 long long h = 0;
7522 for (char c : s)
7523 h = (h * base + c - 'a' + 1) % mod;
7524 return h;
7525}
7526
7527// Estimates the length of the string to very likely have a collision.
7528inline int estimate_length(int alphabet_size, int mod) {
7529 // Magic constants.
7530 double base_len = 2.5 * std::log(std::sqrt(mod));
7531 double scale = std::log(alphabet_size) / std::log(2.0);
7532 double adjusted = base_len / std::max(1.0, scale * 0.7);
7533
7534 return static_cast<int>(std::ceil(adjusted));
7535}
7536
7537// Collides two strings to have the same polynomial hash.
7538// O(sqrt(mod) log(mod)) with high probability.
7539inline std::pair<std::string, std::string>
7540birthday_attack(const std::vector<std::string> &alphabet, int base, int mod) {
7541 tgen_ensure(0 < base and base < mod,
7542 "birthday_attack: base must be in (0, mod)");
7543 std::map<uint64_t, std::vector<int>> seen;
7544 int length = estimate_length(alphabet.size(), mod);
7545
7546 while (true) {
7547 std::vector<int> seq(length);
7548
7549 std::string s;
7550
7551 for (int i = 0; i < length; ++i) {
7552 seq[i] = next<int>(0, alphabet.size() - 1);
7553 s += alphabet[seq[i]];
7554 }
7555
7556 int h = hash_string(s, base, mod);
7557
7558 auto it = seen.find(h);
7559 if (it != seen.end() and it->second != seq) {
7560 std::string a, b;
7561
7562 for (int x : it->second)
7563 a += alphabet[x];
7564 for (int x : seq)
7565 b += alphabet[x];
7566
7567 if (a != b)
7568 return {a, b};
7569 }
7570
7571 seen[h] = seq;
7572 }
7573}
7574
7575// Tried to find correct multipliers for unordered_map/set to force
7576// collisions. O(1).
7577inline std::set<long long> std_hash_multipliers() {
7578 std::set<long long> multipliers = {85229};
7579
7580 // Codeforces GCC GNU G++17 7.3.0 case.
7581 bool codeforces_gcc_case = true;
7582 if (cpp.version_ != 0 and cpp.version_ != 17)
7583 codeforces_gcc_case = false;
7584 if (compiler.kind_ != compiler_kind::unknown and
7585 compiler.kind_ != compiler_kind::gcc)
7586 codeforces_gcc_case = false;
7587 if (compiler.major_ > 7)
7588 codeforces_gcc_case = false;
7589
7590 if (codeforces_gcc_case)
7591 multipliers.insert(107897);
7592
7593 return multipliers;
7594}
7595
7596} // namespace detail
7597
7598// Fetches prefix of length n of the string "abacabadabacabae...".
7599// O(n).
7600inline std::string abacaba(int n) {
7601 tgen_ensure(n > 0, "str: size must be positive");
7602 std::string str = "a";
7603 char c = 'a';
7604 while (static_cast<int>(str.size()) < n) {
7605 int prev_size = str.size();
7606 str += ++c;
7607 for (int j = 0; j < prev_size and static_cast<int>(str.size()) < n; ++j)
7608 str += str[j];
7609 }
7610 return str;
7611}
7612
7613// Two strings that have same polynomial hash for any base, for
7614// mod = power of 2 up to 2^64.
7615// Thue–Morse.
7616// O(1).
7617inline std::pair<std::string, std::string> unsigned_polynomial_hash() {
7618 std::string a, b;
7619 int size = 1 << 10;
7620 for (int i = 0; i < size; ++i) {
7621 a += 'a' + math::detail::popcount(i) % 2;
7622 b += 'a' + ('b' - a[i]);
7623 }
7624 return {a, b};
7625}
7626
7627// Collides two strings to have the same polynomial hash.
7628// O(sqrt(mod) log(mod)) with high probability.
7629// 0 < base < mod.
7630inline std::pair<std::string, std::string> polynomial_hash(int alphabet_size,
7631 int base, int mod) {
7632 tgen_ensure(alphabet_size > 1,
7633 "hack: polynomial_hash: alphabet size must be greater "
7634 "than 1");
7635 tgen_ensure(0 < base and base < mod,
7636 "hack: polynomial_hash: base must be in (0, mod)");
7637
7638 std::vector<std::string> alphabet(alphabet_size);
7639 for (int i = 0; i < alphabet_size; ++i)
7640 alphabet[i] = std::string(1, 'a' + i);
7641 std::iota(alphabet.begin(), alphabet.end(), 'a');
7642 return detail::birthday_attack(alphabet, base, mod);
7643}
7644
7645// Collides two strings to have the same polynomial hash for multiple bases
7646// and mods (up to 2 pairs).
7647// O(sqrt(mod) log^2 (mod)) with high probability,
7648// with mod = max(mod_1, mod_2).
7649inline std::pair<std::string, std::string>
7650polynomial_hash(int alphabet_size, std::vector<int> bases,
7651 std::vector<int> mods) {
7652 tgen_ensure(bases.size() == mods.size(),
7653 "hack: polynomial_hash: bases and mods must have the same "
7654 "size");
7655 tgen_ensure(bases.size() > 0,
7656 "hack: polynomial_hash: must have at least one (base, mod) "
7657 "pair");
7658 tgen_ensure(bases.size() <= 2,
7659 "hack: polynomial_hash: multi-hash hack only supported "
7660 "for up to 2 (base, mod) pairs");
7661
7662 std::vector<std::string> alphabet(alphabet_size);
7663 for (int i = 0; i < alphabet_size; ++i)
7664 alphabet[i] = std::string(1, 'a' + i);
7665 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);
7666 if (bases.size() == 1)
7667 return {S1, T1};
7668 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);
7669}
7670
7671// Returns a list of integers for unordered_map/set to force collisions.
7672// O(size).
7673inline std::vector<long long> std_unordered(int size) {
7674 tgen_ensure(size > 0, "hack: std_unordered: size must be positive");
7675 std::set<long long> multipliers = detail::std_hash_multipliers();
7676 long long mult = 1;
7677 std::set<long long>::iterator it = multipliers.begin();
7678
7679 std::vector<long long> list;
7680 while (static_cast<int>(list.size()) < size) {
7681 list.push_back(mult * (*it));
7682 ++it;
7683 if (it == multipliers.end()) {
7684 it = multipliers.begin();
7685 ++mult;
7686 }
7687 }
7688 return list;
7689}
7690
7691// Returns queries that force \Theta(q sqrt n) asymptotic
7692// for Mo algorithm for offline range queries.
7693// Forces \Theta(q sqrt n) pointer moves for any ordering.
7694// O(n log n + q).
7695inline std::vector<std::pair<int, int>> mo_worst_case(int n, int q) {
7696 std::set<std::pair<int, int>> queries;
7697
7698 // Adversarial case.
7699 int sq = std::sqrt(n);
7700 for (int i = 0; i < sq; ++i) {
7701 for (int j = i; j < sq; ++j) {
7702 if (i * sq < n and j * sq < n)
7703 queries.emplace(i * sq, j * sq);
7704 }
7705 }
7706
7707 // Push extra queries.
7708 for (int i = 0; i < n; ++i)
7709 if (queries.size() < size_t(q)) {
7710 queries.emplace(0, i);
7711 queries.emplace(i, i);
7712 queries.emplace(i, n - 1);
7713 }
7714
7715 std::vector<std::pair<int, int>> pool(queries.begin(), queries.end());
7716 while (pool.size() < size_t(q)) {
7717 int l = next(0, n - 1);
7718 pool.emplace_back(l, next(l, n - 1));
7719 }
7720
7721 return choose(shuffled(pool), q);
7722}
7723
7724// Returns list of strings that have a high cost to insert in a std::set.
7725// Forces cost \Theta(size log(size)).
7726// Generates: {b, ab, aab, aaab, ...}.
7727// O(size log(size)).
7729 std::vector<std::string> list;
7730 int k = 0, left = size;
7731 while (left > 0) {
7732 int cur_size = std::min(left, k + 1);
7733 left -= cur_size;
7734
7735 char right_char = cur_size == k + 1 ? 'b' : 'c';
7736 list.push_back(std::string(cur_size - 1, 'a') + right_char);
7737
7738 ++k;
7739 }
7740 return tgen::shuffled(list);
7741}
7742
7743// Graph for Dijkstra implementations that relax with <= instead of <.
7744// Unit-weight layered graph: 0 -> {1,2}, then disjoint
7745// 2x2 gadgets (i,i+1) -> {i+2,i+3} for i = 1,3,5,... Many vertices share the
7746// same dist from 0; with `d + w <= dist[j]` each pop re-relaxes the whole
7747// frontier below it. m = 2(n - 2) edges.
7748// O(n).
7751 n >= 3,
7752 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");
7753
7754 egraph<int>::value g(n, {}, true);
7755 g.edge_weighted();
7756 g.add_edge(0, 1, 1);
7757 g.add_edge(0, 2, 1);
7758 for (int i = 1; i + 2 < n; i += 2) {
7759 g.add_edge(i, i + 2, 1);
7760 if (i + 3 < n)
7761 g.add_edge(i, i + 3, 1);
7762
7763 g.add_edge(i + 1, i + 2, 1);
7764 if (i + 3 < n)
7765 g.add_edge(i + 1, i + 3, 1);
7766 }
7767
7768 return g.shuffle_except({0});
7769}
7770
7771// Graph for Dijkstra implementations that do not skip stale heap entries
7772// (`if (d > dist[i]) continue`).
7773// Hub mid = n/2: star 0 -> 1..mid-1 (weights 1..mid-1), funnel i -> mid
7774// (weights 1,3,5,...), then mid -> mid+1.. (weight 1).
7775// Without a stale-heap check, mid and its in-neighbors are re-popped and
7776// re-relax.
7777// m = n + mid - 3 edges, mid = floor(n/2).
7778// O(n).
7780 tgen_ensure(n >= 4,
7781 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");
7782
7783 int mid = n / 2;
7784 egraph<int>::value g(n, {}, true);
7785 g.edge_weighted();
7786 for (int i = 1; i < mid; ++i)
7787 g.add_edge(0, i, i);
7788 for (int i = 1; i < mid; ++i)
7789 g.add_edge(i, mid, 2 * (mid - i) - 1);
7790 for (int i = mid + 1; i < n; ++i)
7791 g.add_edge(mid, i, 1);
7792
7793 return g.shuffle_except({0});
7794}
7795
7796// Worst-case for FIFO-SPFA.
7797// Forces Omega(n^2) from vertex 0 (Theta(n*m), m = 2n - 3).
7798// Upper chain ai -> a(i+1) weight 1; lower chain bi -> b(i+1) weight 0;
7799// vertical ai -> bi weight 0; cross bi -> a(i+1) weight 1. Upper chain sets
7800// loose dist first; cross edges from settled bi then improve a(i+1).
7801// m = 2n - 3.
7802// O(n).
7803inline egraph<int>::value spfa(int n) {
7804 tgen_ensure(n >= 2, "hack: spfa: n must be at least 2");
7805 tgen_ensure(n % 2 == 0, "hack: spfa: n must be even");
7806
7807 egraph<int>::value g(n, {}, true);
7808 g.edge_weighted();
7809
7810 const int k = n / 2;
7811 for (int i = 0; i + 1 < k; ++i)
7812 g.add_edge(i, i + 1, 1);
7813 for (int i = 0; i + 1 < k; ++i)
7814 g.add_edge(k + i, k + i + 1, 0);
7815 for (int i = 0; i < k; ++i)
7816 g.add_edge(i, k + i, 0);
7817 for (int i = 0; i + 1 < k; ++i)
7818 g.add_edge(k + i, i + 1, 1);
7819
7820 return g.shuffle_except({0});
7821}
7822
7823// Zadeh (1972) anti-shortest-paths flow network for Edmonds-Karp and Dinitz.
7824// Source is vertex 0; sink is vertex 4l + 2k + 1.
7825// n = 4l + 2k + 2, m = 6l + 4k + k^2 - 4.
7826// O(l + k^2).
7827inline egraph<int>::value dinitz_worst_case(int k, int l) {
7828 tgen_ensure(k >= 1, "hack: dinitz_worst_case: k must be at least 1");
7829 tgen_ensure(l >= 1, "hack: dinitz_worst_case: l must be at least 1");
7830
7831 const int p1 = 2 * l - 1;
7832 const int p2 = 2 * l;
7833 const int q1 = 2 * l + 1;
7834 const int q2 = 2 * l + 2;
7835 const int n = 4 * l + 2 * k + 2;
7836
7837 const int flow_cap = k * k * l;
7838 const int layer_cap = k * k;
7839
7840 auto a = [&](int i) { return 2 * l + 3 + 2 * i; };
7841 auto b = [&](int i) { return 2 * l + 4 + 2 * i; };
7842 auto t = [&](int i) { return 4 * l + 2 * k + 1 - i; };
7843
7844 egraph<int>::value g(n, {}, true);
7845 g.edge_weighted();
7846
7847 for (int i = 0; i + 1 < 2 * l - 1; ++i)
7848 g.add_edge(i, i + 1, flow_cap);
7849 for (int i = 0; i + 1 < 2 * l - 1; ++i)
7850 g.add_edge(t(i + 1), t(i), flow_cap);
7851
7852 for (int i = 0; i < 2 * l - 1; i += 2) {
7853 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);
7854 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);
7855 }
7856
7857 for (int i = 0; i < k; ++i) {
7858 g.add_edge(p1, a(i), flow_cap);
7859 g.add_edge(p2, b(i), flow_cap);
7860 g.add_edge(a(i), q2, flow_cap);
7861 g.add_edge(b(i), q1, flow_cap);
7862 }
7863
7864 for (int i = 0; i < k; ++i)
7865 for (int j = 0; j < k; ++j)
7866 g.add_edge(a(i), b(j), 1);
7867
7868 return g;
7869}
7870
7871// Returns a mask of length 19938, with weights such that xor-ing with mt19937
7872// outputs yields 0.
7873// O(1).
7874template <typename T> std::vector<bool> mt19937_xor_hash() {
7875 static_assert(std::is_same_v<T, int> or std::is_same_v<T, long long>,
7876 "hack: mt19937_xor_hash: T must be int or long long");
7877
7878 constexpr std::size_t deg = 19937;
7879
7880 std::bitset<deg + 1> a, b, c;
7881 b[deg] = c[deg] = 1;
7882 std::size_t l = 0, shift = 1;
7883 std::mt19937 rng32;
7884 std::mt19937_64 rng64;
7885 for (std::size_t n = 0; n < deg * 2; ++n) {
7886 a >>= 1;
7887 if constexpr (std::is_same_v<T, int>)
7888 a[deg] = rng32() & 1;
7889 else
7890 a[deg] = rng64() & 1;
7891
7892 if ((c & a).count() % 2 == 0) {
7893 ++shift;
7894 continue;
7895 }
7896
7897 std::bitset<deg + 1> oc = c;
7898 c ^= (b >> shift);
7899 if (2 * l <= n) {
7900 l = n + 1 - l;
7901 b = oc;
7902 shift = 1;
7903 } else {
7904 ++shift;
7905 }
7906 }
7907
7908 std::vector<bool> mask(deg + 1);
7909 for (std::size_t i = 0; i <= deg; ++i)
7910 mask[i] = c[i];
7911 return mask;
7912}
7913
7914// Convex polygon that breaks naive rotating calipers for maximum vertex
7915// distance (advances j while dist(i, next(j)) > dist(i, j) instead of using
7916// ccw).
7917// O(1).
7918inline std::vector<geometry::point<double>>
7920 return {
7921 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},
7922 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},
7923 };
7924}
7925
7926namespace detail {
7927
7928// Builds a hack block of order k (length fib(2k+1)).
7929// O(fib(2k+1)).
7930inline std::vector<int> segment_tree_beats_worst_case_block(int k) {
7931 tgen_ensure(k >= 1,
7932 "hack: segment_tree_beats_worst_case: k must be at least 1");
7933
7934 std::vector<int> a(k + 1), b(k + 1);
7935 std::vector<std::vector<int>> vf(k + 1), vg(k + 1);
7936
7937 a[1] = b[1] = 1;
7938 vf[1] = {1};
7939 vg[1] = {1, 0};
7940
7941 for (int i = 2; i <= k; ++i) {
7942 b[i] = b[i - 1] + a[i - 1];
7943 a[i] = b[i] + a[i - 1];
7944 for (int x : vf[i - 1])
7945 vf[i].push_back(x + a[i] + b[i]);
7946 vf[i].push_back(a[i]);
7947 for (int x : vg[i - 1])
7948 vf[i].push_back(x + a[i]);
7949 vg[i] = vf[i];
7950 vg[i].push_back(0);
7951 for (int x : vg[i - 1])
7952 vg[i].push_back(x);
7953 }
7954
7955 vf[k].push_back(0);
7956 return vf[k];
7957}
7958
7959// Appends one update round for the tiled array (offset (round * an) mod L).
7960// O(fib(2k+1)).
7961inline void
7962segment_tree_beats_append_round(std::vector<std::vector<int>> &updates,
7963 int block_len, int an, int bn, int n,
7964 int round) {
7965 const int off = (round * an) % block_len;
7966 const int add_off = (off + block_len - bn) % block_len;
7967 for (int k = 0; k < block_len; ++k) {
7968 const int s = k * block_len * block_len;
7969 const int sub_end = off + an;
7970 if (sub_end <= block_len)
7971 updates.push_back({1, s + off, s + sub_end, bn});
7972 else {
7973 updates.push_back({1, s + off, s + block_len, bn});
7974 updates.push_back({1, s, s + (sub_end - block_len), bn});
7975 }
7976 const int add_end = add_off + bn;
7977 if (add_end <= block_len)
7978 updates.push_back({0, s + add_off, s + add_end, an});
7979 else {
7980 updates.push_back({0, s + add_off, s + block_len, an});
7981 updates.push_back({0, s, s + (add_end - block_len), an});
7982 }
7983 }
7984 updates.push_back({2, 0, n, an});
7985 for (int k = 0; k < block_len; ++k) {
7986 const int s = k * block_len * block_len;
7987 updates.push_back({3, s + (off + an - 1) % block_len, 0});
7988 }
7989}
7990
7991} // namespace detail
7992
7993// Array and updates for worst case of segment tree beats.
7994// O(fib(2k+1)^3 + q).
7995inline std::pair<std::vector<int>, std::vector<std::vector<int>>>
7996segment_tree_beats_worst_case(int k, int q) {
7997 tgen_ensure(k >= 1,
7998 "hack: segment_tree_beats_worst_case: k must be at least 1");
7999 tgen_ensure(k <= 7, "hack: segment_tree_beats_worst_case: k too large");
8000 tgen_ensure(q > 0,
8001 "hack: segment_tree_beats_worst_case: q must be positive");
8002
8003 const auto &fib = math::fibonacci();
8004 const int block_len = fib[k * 2 + 1];
8005 const int an = fib[k * 2];
8006 const int bn = fib[k * 2 - 1];
8007
8008 const int len = block_len;
8009 const int total = len * len * len;
8010
8011 std::vector<int> block = detail::segment_tree_beats_worst_case_block(k);
8012 std::vector<int> arr(total, 0);
8013 for (int x = 0; x < block_len; ++x) {
8014 const int s = x * len * len;
8015 for (int i = 0; i < block_len; ++i)
8016 arr[s + i] = block[i];
8017 }
8018
8019 std::vector<std::vector<int>> updates;
8020 updates.reserve(q);
8021 const int n = total;
8022 for (int round = 0; updates.size() < static_cast<std::size_t>(q); ++round) {
8023 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,
8024 round);
8025 if (updates.size() > static_cast<std::size_t>(q))
8026 updates.resize(q);
8027 }
8028 return {arr, updates};
8029}
8030
8031} // namespace hack
8032
8033/*********************
8034 * *
8035 * MISCELLANEOUS *
8036 * *
8037 *********************/
8038
8039namespace misc {
8040
8041// Generates a uniformly random balanced parentheses sequence with k '(' and k
8042// ')'. Valid means that for no prefix there are more ')' than '('.
8043// O(size).
8044inline std::string gen_parenthesis(int size) {
8045 tgen_ensure(size > 0 and size % 2 == 0,
8046 "misc: parenthesis: size must be a positive even number");
8047
8048 int k = size / 2;
8049 std::string s;
8050 int open = 0, close = 0;
8051
8052 for (int i = 0; i < size; ++i) {
8053 if (open == k) {
8054 s += ')';
8055 ++close;
8056 continue;
8057 }
8058 if (open == close) {
8059 s += '(';
8060 ++open;
8061 continue;
8062 }
8063
8064 long long a = k - open, b = k - close, h = open - close;
8065
8066 // Probability of placing '(':
8067 // P('(') = (k - open) * (h + 2) / ((k - open + k - close) * (h + 1))
8068 // Derived from ballot numbers ratio.
8069 long long num = a * (h + 2);
8070 long long den = (a + b) * (h + 1);
8071
8072 if (next<long long>(1, den) <= num) {
8073 s += '(';
8074 ++open;
8075 } else {
8076 s += ')';
8077 ++close;
8078 }
8079 }
8080
8081 return s;
8082}
8083
8084} // namespace misc
8085
8086} // 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:6939
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:6474
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:6872
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:7447
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:7468
wgraph< VWeight, int > vgraph
Vertex-weighted labeled graphs.
Definition tgen.h:6327
graph::value C(int n, bool is_directed=false)
Cycle graph.
Definition tgen.h:6358
wgraph< int, EWeight > egraph
Edge-weighted labeled graphs.
Definition tgen.h:6330
graph::value S(int n)
Star undirected graph.
Definition tgen.h:6382
graph::value K(int n1, int n2)
Complete bipartite undirected graph.
Definition tgen.h:6371
graph::value K(int n)
Complete undirected graph.
Definition tgen.h:6341
wgraph< int, int > graph
Unweighted labeled graphs.
Definition tgen.h:6333
graph::value P(int n, bool is_directed=false)
Path graph.
Definition tgen.h:6347
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:7695
std::vector< bool > mt19937_xor_hash()
Mask that forces a zero XOR hash from std::mt19937 or std::mt19937_64.
Definition tgen.h:7874
egraph< int >::value spfa(int n)
Worst-case for FIFO-SPFA.
Definition tgen.h:7803
egraph< int >::value non_strict_relaxation_dijkstra_bug(int n)
Directed weighted graph for Dijkstra with non-strict relaxation.
Definition tgen.h:7749
std::string abacaba(int n)
Returns the prefix of the infinite word "abacabad...".
Definition tgen.h:7600
std::vector< geometry::point< double > > naive_rotating_calipers_max_dist_bug()
Convex polygon that breaks naive rotating calipers for maximum distance.
Definition tgen.h:7919
std::vector< long long > std_unordered(int size)
List of integers that tries to force collision on std::unordered_set.
Definition tgen.h:7673
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:7728
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:7617
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:7630
egraph< int >::value dinitz_worst_case(int k, int l)
Flow network for Edmonds-Karp and Dinitz worst-case.
Definition tgen.h:7827
egraph< int >::value stale_heap_dijkstra_bug(int n)
Directed weighted graph for Dijkstra without a stale-heap check.
Definition tgen.h:7779
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:3163
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:2984
uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod)
Computes largest congruent up to given value.
Definition tgen.h:3072
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:3097
constexpr int FFT_MOD
FFT/NTT mod.
Definition tgen.h:3078
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:2974
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:3032
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:3081
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:3023
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:3352
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:3261
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:2930
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:8044
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:4977
wtree< int, EWeight > etree
Edge-weighted labeled trees.
Definition tgen.h:4980
wtree< int, int > tree
Unweighted labeled trees.
Definition tgen.h:4983
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:6393
T x() const
x coordinate.
Definition tgen.h:6410
bool operator==(const point &p) const
Coordinate-wise equality.
Definition tgen.h:6433
product_t operator*(const point &p) const
Dot product.
Definition tgen.h:6451
product_t operator^(const point &p) const
Cross product.
Definition tgen.h:6458
point operator*(T c) const
Scalar multiplication.
Definition tgen.h:6448
point operator-(const point &p) const
Vector subtraction.
Definition tgen.h:6443
point(T x=0, T y=0)
Constructs a point.
Definition tgen.h:6407
T y() const
y coordinate.
Definition tgen.h:6413
bool operator<(const point &p) const
Lexicographic order.
Definition tgen.h:6426
point operator+(const point &p) const
Vector addition.
Definition tgen.h:6438
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:4196
T second() const
Returns the second element of a pair value.
Definition tgen.h:4208
value(const T &first, const T &second)
Creates a pair value from first and second values.
Definition tgen.h:4204
value(const std::pair< T, T > &pair)
Creates a pair value from a std::pair.
Definition tgen.h:4203
auto to_std() const
Converts the pair to a std::pair.
Definition tgen.h:4222
T first() const
Returns the first element of a pair value.
Definition tgen.h:4207
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:4211
Pair generator.
Definition tgen.h:4139
value gen() const
Generates a uniformly random value from the set of valid pairs.
Definition tgen.h:4235
pair & neq()
Restricts generator s.t. first is not equal to second.
Definition tgen.h:4166
pair & leq()
Restricts generator s.t. first is less than or equal to second.
Definition tgen.h:4184
pair & lt()
Restricts generator s.t. first is less than second.
Definition tgen.h:4172
pair & gt()
Restricts generator s.t. first is greater than second.
Definition tgen.h:4178
pair(T both_left, T both_right)
Creates pair generator defined by range of values for both first and second.
Definition tgen.h:4156
pair & eq()
Restricts generator s.t. first is equal to second.
Definition tgen.h:4160
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:4147
pair & geq()
Restricts generator s.t. first is greater than or equal to second.
Definition tgen.h:4190
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:3803
char pick() const
Returns a uniformly random element.
Definition tgen.h:3875
char pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the string with given probabilities.
Definition tgen.h:3880
value choose(int k) const
Chooses a uniformly random subsequence of given length.
Definition tgen.h:3893
value & lowercase()
Sets all characters to lowercase.
Definition tgen.h:3845
value & reverse()
Reverses the string.
Definition tgen.h:3838
int size() const
Returns the size of the string value.
Definition tgen.h:3815
value(const std::string &str)
Creates a string value from a std::string.
Definition tgen.h:3810
value & shuffle()
Shuffles the string.
Definition tgen.h:3867
char & operator[](int idx)
Accesses the character at some position of the string.
Definition tgen.h:3818
value & uppercase()
Sets all characters to uppercase.
Definition tgen.h:3853
value operator+(const value &rhs) const
Concatenates two strings.
Definition tgen.h:3861
std::string to_std() const
Converts the string to a std::string.
Definition tgen.h:3914
value & sort()
Sorts the characters in non-decreasing order.
Definition tgen.h:3831
String generator.
Definition tgen.h:3695
str & different(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are different.
Definition tgen.h:3782
str & palindrome(int left, int right)
Restricts generator s.t. range is a palindrome.
Definition tgen.h:3758
value gen() const
Generates a uniformly random value from the set of valid strings.
Definition tgen.h:3920
str(int size, char value_left='a', char value_right='z')
Creates string generator defined by size and range of characters.
Definition tgen.h:3702
str & different(std::set< int > indices)
Restricts generator s.t. all characters in index set are different.
Definition tgen.h:3775
str(const std::string &regex, Args &&...args)
Creates string generator defined by regex.
Definition tgen.h:3715
str & equal(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are equal.
Definition tgen.h:3737
str & equal(std::set< int > indices)
Restricts generator s.t. all characters in index set are equal.
Definition tgen.h:3730
str & equal_range(int left, int right)
Restricts generator s.t. all characters at index range are equal.
Definition tgen.h:3744
str & fix(int idx, char character)
Restricts generator s.t. character at index is fixed.
Definition tgen.h:3723
str & all_equal()
Restricts generator s.t. all values are equal.
Definition tgen.h:3751
str & different_range(int left, int right)
Restricts generator s.t. all characters at index range are different.
Definition tgen.h:3789
str & palindrome()
Restricts generator s.t. string is a palindrome.
Definition tgen.h:3768
str & all_different()
Restricts generator s.t. all characters are different.
Definition tgen.h:3796
str(int size, std::set< char > chars)
Creates string generator defined by character set.
Definition tgen.h:3709
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:5159
value & print_nm()
Prints number of vertices and edges before edge list.
Definition tgen.h:5335
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
Definition tgen.h:5278
value operator!() const
Graph complement of unweighted graph.
Definition tgen.h:5710
std::tuple< int, int, std::vector< std::set< int > > > to_std() const
Converts the graph to std types.
Definition tgen.h:5799
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
Definition tgen.h:5345
value & add_1()
Adds 1 for printing.
Definition tgen.h:5328
int n() const
Number of vertices.
Definition tgen.h:5260
value operator+(const value &rhs) const
Concatenates two graphs (disjoint union).
Definition tgen.h:5744
value & disjoint_union(const value &rhs)
Disjoint union with another graph.
Definition tgen.h:5581
int m() const
Number of edges.
Definition tgen.h:5263
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another graph at given vertex pairs.
Definition tgen.h:5504
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
Definition tgen.h:5283
value(const std::vector< std::set< int > > &adj, bool is_directed=false)
Builds a graph from an adjacency list.
Definition tgen.h:5178
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:5199
wgraph< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
Definition tgen.h:5290
const std::vector< std::set< int > > & adj() const
Adjacency list.
Definition tgen.h:5269
value & add_vertices(int k, std::optional< std::vector< VWeight > > new_vertex_weights=std::nullopt)
Adds new isolated vertices.
Definition tgen.h:5416
value & random_connected_subgraph(int num_edges)
Random subgraph with a fixed number of edges that keeps components connected.
Definition tgen.h:5620
value(const typename wtree< VWeight, EWeight >::value &t)
Builds an undirected graph from a tree.
Definition tgen.h:5230
value & random_subgraph(int num_edges)
Random subgraph with a fixed number of edges.
Definition tgen.h:5587
value & edge_weighted()
Enables edge-weighted mode on an edgeless graph.
Definition tgen.h:5315
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:5477
bool is_directed() const
If the graph is directed.
Definition tgen.h:5266
value & add_edge(int u, int v, std::optional< EWeight > w=std::nullopt)
Adds an edge between two vertices.
Definition tgen.h:5443
value & shuffle()
Shuffles all vertices and edge order.
Definition tgen.h:5411
wgraph< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Definition tgen.h:5304
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Definition tgen.h:5275
Labeled weighted graph generator.
Definition tgen.h:5123
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:5133
static value gen_bipartite(int n1, int n2, int m, bool connected=false)
Generates a random bipartite graph.
Definition tgen.h:6146
value get_connected() const
Random connected undirected graph extending preset edges.
Definition tgen.h:5866
value gen() const
Generates a uniformly random graph satisfying the constraints.
Definition tgen.h:5842
wgraph & add_edge(int u, int v)
Adds a preset edge that must appear in the generated graph.
Definition tgen.h:5141
value get_acyclic() const
Random directed acyclic graph extending preset edges.
Definition tgen.h:5940
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:6043
wgraph & add_edges_from(const value &rhs)
Adds all edges from another graph as preset edges.
Definition tgen.h:5829
Labeled tree value.
Definition tgen.h:4385
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another tree at given vertex pairs.
Definition tgen.h:4688
value & add_1()
Adds 1 for printing.
Definition tgen.h:4526
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Definition tgen.h:4472
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:4422
value(const typename wgraph< VWeight, EWeight >::value &g)
Builds a tree from a graph via a Kruskal-like random spanning tree.
Definition tgen.h:6278
value & print_parents(int root=-1)
Prints in parent format instead of edge list.
Definition tgen.h:4542
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
Definition tgen.h:4475
value & edge_weighted()
Enables edge-weighted mode on an edgeless tree.
Definition tgen.h:4513
int n() const
Returns the number of vertices.
Definition tgen.h:4466
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
Definition tgen.h:4554
const std::vector< std::set< int > > & adj() const
Adjacency list.
Definition tgen.h:4469
value(const std::vector< std::set< int > > &adj)
Builds a tree from an adjacency list.
Definition tgen.h:4402
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
Definition tgen.h:4480
value & shuffle()
Shuffles vertices and edge order.
Definition tgen.h:4623
std::pair< int, std::vector< std::set< int > > > to_std() const
Converts the tree to a std types.
Definition tgen.h:4848
wtree< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
Definition tgen.h:4487
value & print_n()
Prints the number of vertices before the tree.
Definition tgen.h:4533
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:4661
wtree< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Definition tgen.h:4501
Labeled weighted tree generator.
Definition tgen.h:4358
wtree & add_edge(int u, int v)
Restricts generator s.t. some edge is present.
Definition tgen.h:4370
static value gen_skewed(int n, int elongation)
Random skewed tree (large diameter).
Definition tgen.h:4942
value gen() const
Generates a uniformly random value from the set of valid trees.
Definition tgen.h:4885
wtree(int n)
Creates a tree generator with specified number of vertices.
Definition tgen.h:4364
static value gen_kruskal(int n)
Kruskal-like random labeled tree.
Definition tgen.h:4952