tgen 1.4.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 // Restricts adjacent list entries to be different: list[i] != list[i+1].
1676 for (int i = 1; i < size_; ++i)
1677 different(i - 1, i);
1678 return *this;
1679 }
1680
1681 // List value.
1682 // Operations on a value are not random.
1684 using tgen_is_sequential_tag = detail::is_sequential_tag;
1685
1686 using value_type = T; // Value type, for templates.
1687 using std_type = std::vector<T>; // std type for value.
1688
1689 std::vector<T> vec_; // list.
1690 char sep_; // Separator for printing.
1691
1692 value(const std::vector<T> &vec) : vec_(vec), sep_(' ') {}
1693 value(const std::initializer_list<T> &il) : value(std::vector<T>(il)) {}
1694
1695 // Fetches size.
1696 int size() const { return vec_.size(); }
1697
1698 // Fetches position idx.
1699 T &operator[](int idx) {
1700 tgen_ensure(0 <= idx and idx < size(),
1701 "list: value: index out of bounds");
1702 return vec_[idx];
1703 }
1704 const T &operator[](int idx) const {
1705 tgen_ensure(0 <= idx and idx < size(),
1706 "list: value: index out of bounds");
1707 return vec_[idx];
1708 }
1709
1710 // Sorts values in non-decreasing order.
1711 // O(n log n).
1713 std::sort(vec_.begin(), vec_.end());
1714 return *this;
1715 }
1716
1717 // Reverses list.
1718 // O(n).
1720 std::reverse(vec_.begin(), vec_.end());
1721 return *this;
1722 }
1723
1724 // Sets the separator for the list, for printing.
1725 // O(1).
1726 value &separator(char sep) {
1727 sep_ = sep;
1728 return *this;
1729 }
1730
1731 // Concatenates two values.
1732 // Linear.
1733 value operator+(const value &rhs) const {
1734 std::vector<T> new_vec = vec_;
1735 for (int i = 0; i < rhs.size(); ++i)
1736 new_vec.push_back(rhs[i]);
1737 return value(new_vec);
1738 }
1739
1740 // Shuffles list uniformly.
1741 // O(n).
1743 for (int i = 0; i < size(); ++i)
1744 std::swap(vec_[i], vec_[next(0, size() - 1)]);
1745 return *this;
1746 }
1747
1748 // Returns a random element uniformly.
1749 // O(1).
1750 T pick() const { return vec_[next<int>(0, size() - 1)]; }
1751
1752 // Returns vec_[i] with probability proportional to distribution[i].
1753 // O(1).
1754 template <typename Dist>
1755 T pick_by_distribution(const std::vector<Dist> &distribution) const {
1756 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
1757 "value and distribution must have the same size");
1758 return vec_[next_by_distribution(distribution)];
1759 }
1760 template <typename Dist>
1761 T pick_by_distribution(
1762 const std::initializer_list<Dist> &distribution) const {
1763 return pick_by_distribution(std::vector<Dist>(distribution));
1764 }
1765
1766 // Chooses k values uniformly, as in a subsequence of size k.
1767 // O(n).
1768 value choose(int k) const {
1769 tgen_ensure(0 < k and k <= size(),
1770 "number of elements to choose must be valid");
1771 std::vector<T> new_vec;
1772 int need = k;
1773 for (int i = 0; need > 0; ++i) {
1774 int left = size() - i;
1775 if (next(1, left) <= need) {
1776 new_vec.push_back(vec_[i]);
1777 need--;
1778 }
1779 }
1780 return value(new_vec);
1781 }
1782
1783 // Prints to std::ostream, separated by sep_.
1784 friend std::ostream &operator<<(std::ostream &out, const value &val) {
1785 for (int i = 0; i < val.size(); ++i) {
1786 if (i > 0)
1787 out << val.sep_;
1788 out << val[i];
1789 }
1790 return out;
1791 }
1792
1793 // Gets a std::vector representing the value.
1794 auto to_std() const {
1795 if constexpr (!detail::is_generator_value<T>::value) {
1796 return vec_;
1797 } else {
1798 std::vector<typename T::std_type> vec;
1799 for (const auto &i : vec_)
1800 vec.push_back(i.to_std());
1801 return vec;
1802 }
1803 }
1804 };
1805
1806 // Generates list value.
1807 // Optimized for performance (unconstrained and all-different fast paths).
1808 // O(n log n).
1809 value gen() const {
1810 if (diff_restrictions_.empty()) {
1811 if (auto unconstrained = try_gen_unconstrained())
1812 return *unconstrained;
1813 }
1814 if (auto all_different = try_gen_all_different())
1815 return *all_different;
1816
1817 ensure_neigh_allocated();
1818 std::vector<T> vec(size_);
1819 std::vector<bool> defined_idx(
1820 size_, false); // For every index, if it has been set in `vec`.
1821
1822 std::vector<int> comp_id(size_, -1); // Component id of each index.
1823 std::vector<std::vector<int>> comp(size_); // Component of each comp-id.
1824 int comp_count = 0; // Number of different components.
1825
1826 // Defines value of entire component.
1827 auto define_comp = [&](int cur_comp, T val) {
1828 for (int idx : comp[cur_comp]) {
1829 tgen_ensure(!defined_idx[idx]);
1830 vec[idx] = val;
1831 defined_idx[idx] = true;
1832 }
1833 };
1834
1835 // Groups = components.
1836 {
1837 std::vector<bool> vis(size_, false); // Visited for each index.
1838 for (int idx = 0; idx < size_; ++idx)
1839 if (!vis[idx]) {
1840 T new_value;
1841 bool value_defined = false;
1842
1843 // BFS to visit the connected component, grouping equal
1844 // values.
1845 std::queue<int> q({idx});
1846 vis[idx] = true;
1847 std::vector<int> component;
1848 while (!q.empty()) {
1849 int cur_idx = q.front();
1850 q.pop();
1851
1852 component.push_back(cur_idx);
1853
1854 // Checks value.
1855 auto [l, r] = val_range_at(cur_idx);
1856 if (l == r) {
1857 if (!value_defined) {
1858 // We found the value.
1859 value_defined = true;
1860 new_value = l;
1861 } else if (new_value != l) {
1862 // We found a contradiction
1863 throw detail::contradiction_error(
1864 "list",
1865 "tried to set value to `" +
1866 std::to_string(new_value) +
1867 "`, but it was already set as `" +
1868 std::to_string(l) + "`");
1869 }
1870 }
1871
1872 for (int nxt_idx : neigh_[cur_idx]) {
1873 if (!vis[nxt_idx]) {
1874 vis[nxt_idx] = true;
1875 q.push(nxt_idx);
1876 }
1877 }
1878 }
1879
1880 // Group entire component, checking if value is defined.
1881 for (int cur_idx : component) {
1882 comp_id[cur_idx] = comp_count;
1883 comp[comp_id[cur_idx]].push_back(cur_idx);
1884 }
1885
1886 // Defines value if needed.
1887 if (value_defined)
1888 define_comp(comp_count, new_value);
1889
1890 ++comp_count;
1891 }
1892 }
1893
1894 // Initial parsing of different restrictions.
1895 std::vector<std::set<int>> diff_containing_comp_idx(comp_count);
1896 {
1897 int dist_id = 0;
1898 for (const std::set<int> &diff : diff_restrictions_) {
1899 // Checks if there are too many different values.
1900 if (static_cast<uint64_t>(diff.size() - 1) +
1901 static_cast<uint64_t>(value_l_) >
1902 static_cast<uint64_t>(value_r_))
1903 throw detail::contradiction_error(
1904 "list", "tried to generate " +
1905 std::to_string(diff.size()) +
1906 " different values, but the maximum is " +
1907 std::to_string(value_r_ - value_l_ + 1));
1908
1909 // Checks if two values in same component are marked as
1910 // different.
1911 std::set<int> comp_ids;
1912 for (int idx : diff) {
1913 if (comp_ids.count(comp_id[idx]))
1914 throw detail::contradiction_error(
1915 "list", "tried to set two indices as equal and "
1916 "different");
1917 comp_ids.insert(comp_id[idx]);
1918
1919 diff_containing_comp_idx[comp_id[idx]].insert(dist_id);
1920 }
1921 ++dist_id;
1922 }
1923 }
1924
1925 // If some value is in >= 3 sets, then there is a cycle.
1926 for (auto &diff_containing : diff_containing_comp_idx)
1927 if (diff_containing.size() >= 3)
1928 throw detail::complex_restrictions_error(
1929 "list",
1930 "one index cannot be in >= 3 'different' restrictions");
1931
1932 std::vector<bool> vis_diff(diff_restrictions_.size(), false);
1933 std::vector<bool> initially_defined_comp_idx(comp_count, false);
1934
1935 // Fills the value in a tree defined by "different" restrictions.
1936 auto define_tree = [&](int diff_id) {
1937 // The set `diff_restrictions_[diff_id]` can have some
1938 // values that are defined.
1939
1940 // Generates set of already defined values.
1941 std::set<T> defined_values;
1942 for (int idx : diff_restrictions_[diff_id])
1943 if (defined_idx[idx]) {
1944 // Checks if two values in `diff_restrictions_[dist_id]`
1945 // have been set to the same value
1946 if (defined_values.count(vec[idx]))
1947 throw detail::contradiction_error(
1948 "list",
1949 "tried to set two indices as equal and different");
1950
1951 defined_values.insert(vec[idx]);
1952 }
1953
1954 // Generates values in this root "different" restriction.
1955 {
1956 int new_value_count = diff_restrictions_[diff_id].size() -
1957 static_cast<int>(defined_values.size());
1958 std::vector<T> generated_values =
1959 generate_distinct_values(new_value_count, defined_values);
1960 auto val_it = generated_values.begin();
1961 for (int idx : diff_restrictions_[diff_id])
1962 if (defined_idx[idx]) {
1963 // The root can cover these components, but there should
1964 // not be any other defined in this tree.
1965 initially_defined_comp_idx[comp_id[idx]] = false;
1966 } else {
1967 define_comp(comp_id[idx], *val_it);
1968 ++val_it;
1969 }
1970 }
1971
1972 // BFS on the tree of "different" restrictions.
1973 std::queue<std::pair<int, int>> q; // {id, parent id}
1974 q.emplace(diff_id, -1);
1975 vis_diff[diff_id] = true;
1976 while (!q.empty()) {
1977 auto [cur_diff, parent] = q.front();
1978 q.pop();
1979
1980 std::set<int> neigh_diff;
1981 for (int idx : diff_restrictions_[cur_diff])
1982 for (int nxt_diff :
1983 diff_containing_comp_idx[comp_id[idx]]) {
1984 if (nxt_diff == cur_diff or nxt_diff == parent)
1985 continue;
1986
1987 // Cycle found.
1988 if (vis_diff[nxt_diff])
1989 throw detail::complex_restrictions_error(
1990 "list",
1991 "cycle found in 'different' restrictions");
1992
1993 neigh_diff.insert(nxt_diff);
1994 }
1995
1996 for (int nxt_diff : neigh_diff) {
1997 vis_diff[nxt_diff] = true;
1998 q.emplace(nxt_diff, cur_diff);
1999
2000 // Generates this "different" restriction.
2001 std::set<T> nxt_defined_values;
2002 for (int idx2 : diff_restrictions_[nxt_diff])
2003 if (defined_idx[idx2]) {
2004 // There cannot be any more defined. This case is
2005 // when there are values not covered by a single
2006 // "different" restriction in the tree.
2007 if (initially_defined_comp_idx[comp_id[idx2]])
2008 throw detail::complex_restrictions_error(
2009 "list");
2010
2011 nxt_defined_values.insert(vec[idx2]);
2012 }
2013 int new_value_count =
2014 diff_restrictions_[nxt_diff].size() -
2015 static_cast<int>(nxt_defined_values.size());
2016 std::vector<T> generated_values = generate_distinct_values(
2017 new_value_count, nxt_defined_values);
2018 auto val_it = generated_values.begin();
2019 for (int idx2 : diff_restrictions_[nxt_diff])
2020 if (!defined_idx[idx2]) {
2021 define_comp(comp_id[idx2], *val_it);
2022 ++val_it;
2023 }
2024 }
2025 }
2026 };
2027
2028 // Loops through "different" restrictions, sorts "different"
2029 // restrictions by number of defined components (non-increasing). This
2030 // guarantees that if there is a valid root (that covers all 'defined'),
2031 // we find it.
2032 {
2033 std::vector<std::pair<int, int>> defined_cnt_and_diff_idx;
2034 int dist_id = 0;
2035 for (const std::set<int> &diff : diff_restrictions_) {
2036 int defined_cnt = 0;
2037 for (int idx : diff)
2038 if (defined_idx[idx]) {
2039 ++defined_cnt;
2040 initially_defined_comp_idx[comp_id[idx]] = true;
2041 }
2042 defined_cnt_and_diff_idx.emplace_back(defined_cnt, dist_id);
2043 ++dist_id;
2044 }
2045
2046 std::sort(defined_cnt_and_diff_idx.rbegin(),
2047 defined_cnt_and_diff_idx.rend());
2048 for (auto [defined_cnt, diff_idx] : defined_cnt_and_diff_idx)
2049 if (!vis_diff[diff_idx])
2050 define_tree(diff_idx);
2051 }
2052
2053 // Loops through "different" restrictions do define the rest.
2054 for (std::size_t dist_id = 0; dist_id < diff_restrictions_.size();
2055 ++dist_id)
2056 if (!vis_diff[dist_id])
2057 define_tree(dist_id);
2058
2059 // Define final values. These values all should be random in [l, r], and
2060 // the "different" restrictions have already been processed. However,
2061 // there can be still equality restrictions, so we define entire
2062 // components.
2063 for (int idx = 0; idx < size_; ++idx)
2064 if (!defined_idx[idx])
2065 define_comp(comp_id[idx], next<T>(value_l_, value_r_));
2066
2067 if (!values_.empty()) {
2068 // Needs to fetch the values from the value set.
2069 std::vector<T> value_vec(values_.begin(), values_.end());
2070 for (T &val : vec)
2071 val = value_vec[val];
2072 }
2073
2074 return value(vec);
2075 }
2076
2077 private:
2078 // Materializes neigh_ after the first equality restriction.
2079 void ensure_neigh_allocated() const {
2080 if (neigh_.size() == static_cast<size_t>(size_))
2081 return;
2082 neigh_.assign(size_, {});
2083 }
2084
2085 // Materializes val_range_ after the first per-index restriction.
2086 void ensure_val_range_materialized() const {
2087 if (!uses_full_range_)
2088 return;
2089 val_range_.assign(size_, {value_l_, value_r_});
2090 uses_full_range_ = false;
2091 }
2092
2093 // Returns the allowed value range at index idx.
2094 std::pair<T, T> val_range_at(int idx) const {
2095 if (uses_full_range_)
2096 return {value_l_, value_r_};
2097 return val_range_[idx];
2098 }
2099
2100 // Generates a uniformly random list of k distinct values in `[value_l,
2101 // value_r]`, such that no value is in `forbidden_values`.
2102 std::vector<T>
2103 generate_distinct_values(int k, const std::set<T> &forbidden_values) const {
2104 for (auto forbidden : forbidden_values)
2105 tgen_ensure(value_l_ <= forbidden and forbidden <= value_r_);
2106 const T num_available =
2107 (value_r_ - value_l_ + 1) - forbidden_values.size();
2108 if (num_available < k)
2109 throw detail::complex_restrictions_error(
2110 "list", "not enough distinct values");
2111 if (forbidden_values.empty())
2112 return distinct_range<T>(value_l_, value_r_).gen_list(k).to_std();
2113
2114 std::map<T, T> virtual_list;
2115 std::vector<T> gen_list;
2116 for (int i = 0; i < k; ++i) {
2117 T j = next<T>(i, num_available - 1);
2118 T vj = virtual_list.count(j) ? virtual_list[j] : j;
2119 T vi = virtual_list.count(i) ? virtual_list[i] : i;
2120
2121 virtual_list[j] = vi, virtual_list[i] = vj;
2122
2123 gen_list.push_back(virtual_list[i]);
2124 }
2125
2126 for (T &val : gen_list)
2127 val += value_l_;
2128
2129 std::vector<std::pair<T, int>> values_sorted;
2130 for (std::size_t i = 0; i < gen_list.size(); ++i)
2131 values_sorted.emplace_back(gen_list[i], i);
2132 std::sort(values_sorted.begin(), values_sorted.end());
2133 auto cur_it = forbidden_values.begin();
2134 int smaller_forbidden_count = 0;
2135 for (auto [val, idx] : values_sorted) {
2136 while (cur_it != forbidden_values.end() and
2137 *cur_it <= val + smaller_forbidden_count)
2138 ++cur_it, ++smaller_forbidden_count;
2139 gen_list[idx] += smaller_forbidden_count;
2140 }
2141
2142 return gen_list;
2143 }
2144
2145 // If this generator has no constraints beyond [value_l_, value_r_],
2146 // returns independent uniform samples; otherwise returns std::nullopt.
2147 // O(n).
2148 std::optional<value> try_gen_unconstrained() const {
2149 if (!values_.empty() or index_constraints_)
2150 return std::nullopt;
2151
2152 std::vector<T> vec(size_);
2153 for (int i = 0; i < size_; ++i)
2154 vec[i] = next<T>(value_l_, value_r_);
2155 return value(vec);
2156 }
2157
2158 // If this generator is exactly all-distinct in [value_l_, value_r_],
2159 // returns a uniformly random list; otherwise returns std::nullopt.
2160 // Optimized for performance (distinct_range fast path).
2161 // O(n log n).
2162 std::optional<value> try_gen_all_different() const {
2163 if (!values_.empty() or diff_restrictions_.size() != 1)
2164 return std::nullopt;
2165
2166 const std::set<int> &diff = diff_restrictions_[0];
2167 if (static_cast<int>(diff.size()) != size_ or *diff.begin() != 0 or
2168 *diff.rbegin() != size_ - 1)
2169 return std::nullopt;
2170
2171 if (!neigh_.empty()) {
2172 for (const auto &adj : neigh_) {
2173 if (!adj.empty())
2174 return std::nullopt;
2175 }
2176 }
2177
2178 if (index_constraints_)
2179 return std::nullopt;
2180
2181 if (static_cast<long long>(size_) >
2182 static_cast<long long>(value_r_) - value_l_ + 1)
2183 throw detail::contradiction_error(
2184 "list", "tried to generate " + std::to_string(size_) +
2185 " different values, but the maximum is " +
2186 std::to_string(value_r_ - value_l_ + 1));
2187
2188 return distinct_range<T>(value_l_, value_r_).gen_list(size_);
2189 }
2190};
2191
2192/*******************
2193 * *
2194 * PERMUTATION *
2195 * *
2196 *******************/
2197
2198/*
2199 * Permutation generation.
2200 *
2201 * Permutation are defined always as numbers in [0, n), that is, 0-based.
2202 */
2203
2205 int size_; // Size of permutation.
2206 std::vector<std::pair<int, int>> defs_; // {idx, value}.
2207 std::optional<std::vector<int>> cycle_sizes_; // Cycle sizes.
2208
2209 // Creates generator for permutation of size 'size'.
2210 permutation(int size) : size_(size) {
2211 tgen_ensure(size_ > 0, "permutation: size must be positive");
2212 }
2213
2214 // Restricts permutations for permutation[idx] = val.
2215 permutation &fix(int idx, int val) {
2216 tgen_ensure(0 <= idx and idx < size_,
2217 "permutation: index must be valid");
2218 defs_.emplace_back(idx, val);
2219 return *this;
2220 }
2221
2222 // Restricts permutations for permutation to have cycle sizes.
2223 permutation &cycles(const std::vector<int> &cycle_sizes) {
2225 size_ == std::accumulate(cycle_sizes.begin(), cycle_sizes.end(), 0),
2226 "permutation: cycle sizes must add up to size of permutation");
2227 cycle_sizes_ = cycle_sizes;
2228 return *this;
2229 }
2230 permutation &cycles(const std::initializer_list<int> &cycle_sizes) {
2231 return cycles(std::vector<int>(cycle_sizes));
2232 }
2233
2234 // Permutation value.
2235 // Operations on a value are not random.
2237 using tgen_is_sequential_tag = detail::is_sequential_tag;
2238
2239 using std_type = std::vector<int>; // std type for value.
2240 std::vector<int> vec_; // Permutation.
2241 char sep_; // Separator for printing.
2242 bool print_1_based_; // If should print values 1-based (print only).
2243
2244 value(const std::vector<int> &vec)
2245 : vec_(vec), sep_(' '), print_1_based_(false) {
2246 tgen_ensure(!vec_.empty(), "permutation: value: cannot be empty");
2247 std::vector<bool> vis(vec_.size(), false);
2248 for (int i = 0; i < size(); ++i) {
2249 tgen_ensure(0 <= vec_[i] and
2250 vec_[i] < static_cast<int>(vec_.size()),
2251 "permutation: value: values must be from `0` to "
2252 "`size-1`");
2253 tgen_ensure(!vis[vec_[i]],
2254 "permutation: value: cannot have repeated values");
2255 vis[vec_[i]] = true;
2256 }
2257 }
2258 value(const std::initializer_list<int> &il)
2259 : value(std::vector<int>(il)) {}
2260
2261 // Fetches size.
2262 int size() const { return vec_.size(); }
2263
2264 // Fetches position idx.
2265 const int &operator[](int idx) const {
2266 tgen_ensure(0 <= idx and idx < size(),
2267 "permutation: value: index out of bounds");
2268 return vec_[idx];
2269 }
2270
2271 // Returns parity of the permutation (+1 if even, -1 if odd).
2272 // O(n).
2273 int parity() const {
2274 std::vector<bool> vis(size(), false);
2275 int cycles = 0;
2276
2277 for (int i = 0; i < size(); ++i)
2278 if (!vis[i]) {
2279 ++cycles;
2280 for (int j = i; !vis[j]; j = vec_[j])
2281 vis[j] = true;
2282 }
2283 // Even iff (n - cycles) is even.
2284 return ((size() - cycles) % 2 == 0) ? +1 : -1;
2285 }
2286
2287 // Sorts values in increasing order.
2288 // O(n).
2290 for (int i = 0; i < size(); ++i)
2291 vec_[i] = i;
2292 return *this;
2293 }
2294
2295 // Reverses permutation.
2296 // O(n).
2298 std::reverse(vec_.begin(), vec_.end());
2299 return *this;
2300 }
2301
2302 // Inverse of the permutation.
2303 // O(n).
2305 std::vector<int> inv(size());
2306 for (int i = 0; i < size(); ++i)
2307 inv[vec_[i]] = i;
2308 swap(vec_, inv);
2309 return *this;
2310 }
2311
2312 // Sets the separator, for printing.
2313 // O(1).
2314 value &separator(char sep) {
2315 sep_ = sep;
2316 return *this;
2317 }
2318
2319 // Sets that should print values 1-based. Does not change stored
2320 // values or to_std(); use to_std_1_based() for a 1-based export.
2321 // O(1).
2323 print_1_based_ = true;
2324 return *this;
2325 }
2326
2327 // Shuffles permutation uniformly.
2328 // O(n).
2330 for (int i = 0; i < size(); ++i)
2331 std::swap(vec_[i], vec_[next(0, size() - 1)]);
2332 return *this;
2333 }
2334
2335 // Returns a random element uniformly.
2336 // O(1).
2337 int pick() const { return vec_[next<int>(0, size() - 1)]; }
2338
2339 // Returns vec_[i] with probability proportional to distribution[i].
2340 // O(1).
2341 template <typename Dist>
2342 int pick_by_distribution(const std::vector<Dist> &distribution) const {
2343 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
2344 "value and distribution must have the same size");
2345 return vec_[next_by_distribution(distribution)];
2346 }
2347 template <typename Dist>
2348 int pick_by_distribution(
2349 const std::initializer_list<Dist> &distribution) const {
2350 return pick_by_distribution(std::vector<Dist>(distribution));
2351 }
2352
2353 // Prints to std::ostream, separated by sep_.
2354 friend std::ostream &operator<<(std::ostream &out, const value &val) {
2355 for (int i = 0; i < val.size(); ++i) {
2356 if (i > 0)
2357 out << val.sep_;
2358 out << val[i] + val.print_1_based_;
2359 }
2360 return out;
2361 }
2362
2363 // Gets a std::vector representing the value (0-based). Unaffected by
2364 // print_1_based().
2365 std::vector<int> to_std() const { return std_type(vec_); }
2366
2367 // Gets a 1-based std::vector (each element +1). Unaffected by
2368 // print_1_based().
2369 std::vector<int> to_std_1_based() const {
2370 std::vector<int> out = vec_;
2371 for (int &x : out)
2372 ++x;
2373 return out;
2374 }
2375 };
2376
2377 // Generates permutation value.
2378 // O(n).
2379 value gen() const {
2380 if (!cycle_sizes_) {
2381 // Cycle sizes not specified.
2382 std::vector<int> idx_to_val(size_, -1), val_to_idx(size_, -1);
2383 for (auto [idx, val] : defs_) {
2385 0 <= val and val < size_,
2386 "permutation: value in permutation must be in [0, " +
2387 std::to_string(size_) + ")");
2388
2389 if (idx_to_val[idx] != -1) {
2390 tgen_ensure(idx_to_val[idx] == val,
2391 "permutation: cannot set an index to two "
2392 "different values");
2393 } else
2394 idx_to_val[idx] = val;
2395
2396 if (val_to_idx[val] != -1) {
2397 tgen_ensure(val_to_idx[val] == idx,
2398 "permutation: cannot set two indices to the "
2399 "same value");
2400 } else
2401 val_to_idx[val] = idx;
2402 }
2403
2404 std::vector<int> perm(size_);
2405 std::iota(perm.begin(), perm.end(), 0);
2406 shuffle(perm.begin(), perm.end());
2407 int cur_idx = 0;
2408 for (int &i : idx_to_val)
2409 if (i == -1) {
2410 // While this value is used, skip.
2411 while (val_to_idx[perm[cur_idx]] != -1)
2412 ++cur_idx;
2413 i = perm[cur_idx++];
2414 }
2415 return idx_to_val;
2416 }
2417
2418 // Creates cycles.
2419 std::vector<int> order(size_);
2420 std::iota(order.begin(), order.end(), 0);
2421 shuffle(order.begin(), order.end());
2422 int idx = 0;
2423 std::vector<std::vector<int>> cycles;
2424 for (int cycle_size : *cycle_sizes_) {
2425 cycles.emplace_back();
2426 for (int i = 0; i < cycle_size; ++i)
2427 cycles.back().push_back(order[idx++]);
2428 }
2429
2430 // Retrieves permutation from cycles.
2431 std::vector<int> perm(size_, -1);
2432 for (const std::vector<int> &cycle : cycles) {
2433 int cur_size = cycle.size();
2434 for (int i = 0; i < cur_size; ++i)
2435 perm[cycle[i]] = cycle[(i + 1) % cur_size];
2436 }
2437
2438 return value(perm);
2439 }
2440};
2441
2442/************
2443 * *
2444 * MATH *
2445 * *
2446 ************/
2447
2448namespace math {
2449
2450namespace detail {
2451
2452using namespace tgen::detail;
2453
2454inline int popcount(uint64_t x) { return __builtin_popcountll(x); }
2455
2456inline int ctzll(uint64_t x) {
2457 // Mystery code found on the internet.
2458 // Uses de Bruijn sequence.
2459 static const unsigned char index64[64] = {
2460 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
2461 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
2462 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
2463 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12};
2464 return index64[((x & -x) * 0x022FDD63CC95386D) >> 58];
2465}
2466
2467inline uint64_t mul_mod(uint64_t a, uint64_t b, uint64_t m) {
2468 return static_cast<u128>(a) * b % m;
2469}
2470
2471// O(log n).
2472// 0 <= x < m.
2473inline uint64_t expo_mod(uint64_t x, uint64_t y, uint64_t m) {
2474 if (!y)
2475 return 1;
2476 uint64_t ans = expo_mod(mul_mod(x, x, m), y / 2, m);
2477 return y % 2 ? mul_mod(x, ans, m) : ans;
2478}
2479
2480} // namespace detail
2481
2482// O(log^2 n).
2483inline bool is_prime(uint64_t n) {
2484 if (n < 2)
2485 return false;
2486 if (n == 2 or n == 3)
2487 return true;
2488 if (n % 2 == 0)
2489 return false;
2490
2491 uint64_t r = detail::ctzll(n - 1), d = n >> r;
2492 // These bases are guaranteed to work for n <= 2^64.
2493 for (int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
2494 uint64_t x = detail::expo_mod(a, d, n);
2495 if (x == 1 or x == n - 1 or a % n == 0)
2496 continue;
2497
2498 for (uint64_t j = 0; j < r - 1; ++j) {
2499 x = detail::mul_mod(x, x, n);
2500 if (x == n - 1)
2501 break;
2502 }
2503 if (x != n - 1)
2504 return false;
2505 }
2506 return true;
2507}
2508
2509namespace detail {
2510
2511inline uint64_t pollard_rho(uint64_t n) {
2512 if (n == 1 or is_prime(n))
2513 return n;
2514 auto f = [n](uint64_t x) { return mul_mod(x, x, n) + 1; };
2515
2516 uint64_t x = 0, y = 0, t = 30, prd = 2, x0 = 1, q;
2517 while (t % 40 != 0 or std::gcd(prd, n) == 1) {
2518 if (x == y)
2519 x = ++x0, y = f(x);
2520 q = mul_mod(prd, x > y ? x - y : y - x, n);
2521 if (q != 0)
2522 prd = q;
2523 x = f(x), y = f(f(y)), ++t;
2524 }
2525 return std::gcd(prd, n);
2526}
2527
2528inline std::vector<uint64_t> factor(uint64_t n) {
2529 if (n == 1)
2530 return {};
2531 if (is_prime(n))
2532 return {n};
2533 uint64_t d = pollard_rho(n);
2534 std::vector<uint64_t> l = factor(d), r = factor(n / d);
2535 l.insert(l.end(), r.begin(), r.end());
2536 return l;
2537}
2538
2539// Error handling.
2540template <typename T>
2541std::runtime_error there_is_no_in_range_error(const std::string &type, T l,
2542 T r) {
2543 return error("math: there is no " + type + " in range [" +
2544 std::to_string(l) + ", " + std::to_string(r) + "]");
2545}
2546template <typename T>
2547std::runtime_error there_is_no_from_error(const std::string &type, T r) {
2548 return error("math: there is no " + type + " from " + std::to_string(r));
2549}
2550template <typename T>
2551std::runtime_error there_is_no_upto_error(const std::string &type, T r) {
2552 return error("math: there is no " + type + " up to " + std::to_string(r));
2553}
2554
2555// O(log mod).
2556// 0 < a < mod.
2557// gcd(a, mod) = 1.
2558inline i128 modular_inverse_128(i128 a, i128 mod) {
2559 tgen_ensure(0 < a and a < mod,
2560 "math: modular inverse requires 0 < value < mod");
2561
2562 i128 t = 0, new_t = 1;
2563 i128 r = mod, new_r = a;
2564
2565 while (new_r != 0) {
2566 i128 q = r / new_r;
2567
2568 auto tmp_t = t - q * new_t;
2569 t = new_t;
2570 new_t = tmp_t;
2571
2572 auto tmp_r = r - q * new_r;
2573 r = new_r;
2574 new_r = tmp_r;
2575 }
2576
2577 tgen_ensure(r == 1, "math: remainder and mod must be coprime");
2578
2579 if (t < 0)
2580 t += mod;
2581 return t;
2582}
2583
2584// checks if a * b <= limit, for positive numbers.
2585inline bool mul_leq(uint64_t a, uint64_t b, uint64_t limit) {
2586 if (a == 0 or b == 0)
2587 return true;
2588 return a <= limit / b;
2589}
2590
2591// base^exp, or null if base^exp > limit.
2592inline std::optional<uint64_t> expo(uint64_t base, uint64_t exp,
2593 uint64_t limit) {
2594 uint64_t result = 1;
2595
2596 while (exp) {
2597 if (exp & 1) {
2598 if (!mul_leq(result, base, limit))
2599 return std::nullopt;
2600 result *= base;
2601 }
2602
2603 exp >>= 1;
2604 // Necessary for correctness.
2605 if (!exp)
2606 break;
2607
2608 if (!mul_leq(base, base, limit))
2609 return std::nullopt;
2610 base *= base;
2611 }
2612 return result;
2613}
2614
2615// O(log n log k).
2616// 0 < k.
2617inline uint64_t kth_root_floor(uint64_t n, uint64_t k) {
2618 tgen_ensure_against_bug(k > 0, "math: value must be valid");
2619 if (k == 1 or n <= 1)
2620 return n;
2621
2622 uint64_t lo = 1, hi = 1ULL << ((64 + k - 1) / k);
2623
2624 while (lo < hi) {
2625 uint64_t mid = lo + (hi - lo + 1) / 2;
2626
2627 if (expo(mid, k, n)) {
2628 lo = mid;
2629 } else {
2630 hi = mid - 1;
2631 }
2632 }
2633 return lo;
2634}
2635
2636// gcd(a, b).
2637// O(log a).
2638inline i128 gcd128(i128 a, i128 b) {
2639 if (a < 0)
2640 a = -a;
2641 if (b < 0)
2642 b = -b;
2643 while (b != 0) {
2644 i128 t = a % b;
2645 a = b;
2646 b = t;
2647 }
2648 return a;
2649}
2650
2651// min(2^64, a*b).
2652// O(log a).
2653// a, b >= 0.
2654inline i128 mul_saturate(i128 a, i128 b) {
2655 tgen_ensure(a >= 0 and b >= 0);
2656 static const i128 LIMIT = static_cast<i128>(1) << 64;
2657 if (a == 0 or b == 0)
2658 return 0;
2659 if (a > LIMIT / b)
2660 return LIMIT;
2661 return a * b;
2662}
2663
2664struct crt {
2665 using T = i128;
2666 T a, m;
2667
2668 crt() : a(0), m(1) {}
2669 crt(T a_, T m_) : a(a_), m(m_) {}
2670 crt operator*(crt C) {
2671 if (m == 0 or C.m == 0)
2672 return {-1, 0};
2673
2674 T g = gcd128(m, C.m);
2675 if ((C.a - a) % g != 0)
2676 return {-1, 0};
2677
2678 T m1 = m / g;
2679 T m2 = C.m / g;
2680
2681 if (m2 == 1)
2682 return {a, m};
2683
2684 T inv = modular_inverse_128(m1 % m2, m2);
2685
2686 T k = ((C.a - a) / g) % m2;
2687 if (k < 0)
2688 k += m2;
2689
2690 k = static_cast<u128>(k) * inv % m2;
2691
2692 T lcm = mul_saturate(m, m2);
2693
2694 T res = (a + static_cast<T>((static_cast<u128>(k) * m) % lcm)) % lcm;
2695 if (res < 0)
2696 res += lcm;
2697
2698 return {res, lcm};
2699 }
2700};
2701
2702// Math hacks to operate on log space.
2703
2704inline constexpr long double LOG_ZERO = -INFINITY;
2705inline constexpr long double LOG_ONE = 0.0;
2706
2707inline long double log_space(long double x) {
2708 return x == 0.0 ? LOG_ZERO : std::log(x);
2709}
2710
2711// Math hack to add two values in log space.
2712inline long double add_log_space(long double a, long double b) {
2713 if (a < b)
2714 std::swap(a, b);
2715 if (b == LOG_ZERO)
2716 return a;
2717 return a + log1p(exp(b - a));
2718}
2719
2720// Math hack to subtract two values in log space.
2721// a >= b.
2722inline long double sub_log_space(long double a, long double b) {
2723 if (b >= a)
2724 return LOG_ZERO;
2725 if (b == LOG_ZERO)
2726 return a;
2727 return a + log1p(-exp(b - a));
2728}
2729
2730} // namespace detail
2731
2732// Sorted.
2733// O(n^(1/4) log n) expected.
2734// 0 < n.
2735inline std::vector<uint64_t> factor(uint64_t n) {
2736 tgen_ensure(n > 0, "math: number to factor must be positive");
2737 auto factors = detail::factor(n);
2738 std::sort(factors.begin(), factors.end());
2739 return factors;
2740}
2741
2742// Sorted.
2743// O(n^(1/4) log n) expected.
2744// 0 < n.
2745inline std::vector<std::pair<uint64_t, int>> factor_by_prime(uint64_t n) {
2746 tgen_ensure(n > 0, "math: number to factor must be positive");
2747 std::vector<std::pair<uint64_t, int>> primes;
2748 for (uint64_t p : factor(n)) {
2749 if (!primes.empty() and primes.back().first == p)
2750 ++primes.back().second;
2751 else
2752 primes.emplace_back(p, 1);
2753 }
2754 return primes;
2755}
2756
2757// O(log mod).
2758// 0 < a < mod.
2759// gcd(a, mod) = 1.
2760inline uint64_t modular_inverse(uint64_t a, uint64_t mod) {
2761 return detail::modular_inverse_128(a, mod);
2762}
2763
2764// O(n^(1/4) log n) expected.
2765// 0 < n.
2766inline uint64_t totient(uint64_t n) {
2767 tgen_ensure(n > 0, "math: totient(0) is undefined");
2768 uint64_t phi = n;
2769
2770 for (auto [p, e] : factor_by_prime(n))
2771 phi -= phi / p;
2772
2773 return phi;
2774}
2775
2776// Returns `(p_i, g_i)`: `p_i` is the prime, `g_i` is the gap.
2777inline const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> &
2778prime_gaps() {
2779 // From https://en.wikipedia.org/wiki/Prime_gap.
2780 static const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> value{
2781 /* clang-format off */ {
2782 2, 3, 7, 23, 89, 113, 523, 887, 1129, 1327, 9551, 15683, 19609,
2783 31397, 155921, 360653, 370261, 492113, 1349533, 1357201, 2010733,
2784 4652353, 17051707, 20831323, 47326693, 122164747, 189695659,
2785 191912783, 387096133, 436273009, 1294268491, 1453168141,
2786 2300942549, 3842610773, 4302407359, 10726904659, 20678048297,
2787 22367084959, 25056082087, 42652618343, 127976334671, 182226896239,
2788 241160624143, 297501075799, 303371455241, 304599508537,
2789 416608695821, 461690510011, 614487453523, 738832927927,
2790 1346294310749, 1408695493609, 1968188556461, 2614941710599,
2791 7177162611713, 13829048559701, 19581334192423, 42842283925351,
2792 90874329411493, 171231342420521, 218209405436543, 1189459969825483,
2793 1686994940955803, 1693182318746371, 43841547845541059,
2794 55350776431903243, 80873624627234849, 203986478517455989,
2795 218034721194214273, 305405826521087869, 352521223451364323,
2796 401429925999153707, 418032645936712127, 804212830686677669,
2797 1425172824437699411, 5733241593241196731, 6787988999657777797
2798 }, /* clang-format on */
2799 {1, 2, 4, 6, 8, 14, 18, 20, 22, 34, 36,
2800 44, 52, 72, 86, 96, 112, 114, 118, 132, 148, 154,
2801 180, 210, 220, 222, 234, 248, 250, 282, 288, 292, 320,
2802 336, 354, 382, 384, 394, 456, 464, 468, 474, 486, 490,
2803 500, 514, 516, 532, 534, 540, 582, 588, 602, 652, 674,
2804 716, 766, 778, 804, 806, 906, 916, 924, 1132, 1184, 1198,
2805 1220, 1224, 1248, 1272, 1328, 1356, 1370, 1442, 1476, 1488, 1510}};
2806
2807 return value;
2808}
2809
2810// Returns pair (first_composite_in_gap, last_composite_in_gap).
2811// O(log(right)) approximately.
2812inline std::pair<uint64_t, uint64_t> prime_gap_upto(uint64_t right) {
2813 if (right < 4)
2814 throw detail::there_is_no_upto_error("prime gap", right);
2815
2816 const auto &[P, G] = prime_gaps();
2817 for (int i = P.size() - 1;; --i) {
2818 if (P[i] >= right)
2819 continue;
2820
2821 uint64_t real_right = std::min(right, P[i] + G[i] - 1);
2822 uint64_t prev = i > 0 ? G[i - 1] : 0;
2823 uint64_t curr = real_right - P[i];
2824
2825 if (curr >= prev)
2826 return {P[i] + 1, real_right};
2827 }
2828}
2829
2830// From https://oeis.org/A002182/b002182.txt.
2832 /* clang-format off */
2833 static const std::vector<uint64_t> highly_composites = {
2834 1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680,
2835 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440,
2836 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280,
2837 720720, 1081080, 1441440, 2162160, 2882880, 3603600, 4324320, 6486480,
2838 7207200, 8648640, 10810800, 14414400, 17297280, 21621600, 32432400,
2839 36756720, 43243200, 61261200, 73513440, 110270160, 122522400, 147026880,
2840 183783600, 245044800, 294053760, 367567200, 551350800, 698377680, 735134400,
2841 1102701600, 1396755360, 2095133040, 2205403200, 2327925600, 2793510720,
2842 3491888400, 4655851200, 5587021440, 6983776800, 10475665200, 13967553600,
2843 20951330400, 27935107200, 41902660800, 48886437600, 64250746560,
2844 73329656400, 80313433200, 97772875200, 128501493120, 146659312800,
2845 160626866400, 240940299600, 293318625600, 321253732800, 481880599200,
2846 642507465600, 963761198400, 1124388064800, 1606268664000, 1686582097200,
2847 1927522396800, 2248776129600, 3212537328000, 3373164194400, 4497552259200,
2848 6746328388800, 8995104518400, 9316358251200, 13492656777600, 18632716502400,
2849 26985313555200, 27949074753600, 32607253879200, 46581791256000,
2850 48910880818800, 55898149507200, 65214507758400, 93163582512000,
2851 97821761637600, 130429015516800, 195643523275200, 260858031033600,
2852 288807105787200, 391287046550400, 577614211574400, 782574093100800,
2853 866421317361600, 1010824870255200, 1444035528936000, 1516237305382800,
2854 1732842634723200, 2021649740510400, 2888071057872000, 3032474610765600,
2855 4043299481020800, 6064949221531200, 8086598962041600, 10108248702552000,
2856 12129898443062400, 18194847664593600, 20216497405104000, 24259796886124800,
2857 30324746107656000, 36389695329187200, 48519593772249600, 60649492215312000,
2858 72779390658374400, 74801040398884800, 106858629141264000,
2859 112201560598327200, 149602080797769600, 224403121196654400,
2860 299204161595539200, 374005201994424000, 448806242393308800,
2861 673209363589963200, 748010403988848000, 897612484786617600,
2862 1122015605983272000, 1346418727179926400, 1795224969573235200,
2863 2244031211966544000, 2692837454359852800, 3066842656354276800,
2864 4381203794791824000, 4488062423933088000, 6133685312708553600,
2865 8976124847866176000, 9200527969062830400, 12267370625417107200ULL,
2866 15334213281771384000ULL, 18401055938125660800ULL}; /* clang-format on */
2867 return highly_composites;
2868}
2869
2870// O(log(right)) approximately.
2871inline uint64_t highly_composite_upto(uint64_t right) {
2872 for (int i = highly_composites().size() - 1; i >= 0; --i)
2873 if (highly_composites()[i] <= right)
2874 return highly_composites()[i];
2875
2876 throw detail::there_is_no_upto_error("highly composite number", right);
2877}
2878
2879// O(log^3 (right)) expected.
2880// Generates a random prime in [left, right].
2881inline uint64_t gen_prime(uint64_t left, uint64_t right) {
2882 if (right < left or right < 2)
2883 throw detail::there_is_no_in_range_error("prime", left, right);
2884 left = std::max<uint64_t>(left, 2);
2885 auto [l_gap, r_gap] = prime_gap_upto(right);
2886 if (right - left + 1 <= r_gap - l_gap + 1) {
2887 // There might be no primes in the range.
2888 std::vector<uint64_t> vals(right - left + 1);
2889 iota(vals.begin(), vals.end(), left);
2890 shuffle(vals.begin(), vals.end());
2891 for (uint64_t i : vals)
2892 if (is_prime(i))
2893 return i;
2894 throw detail::there_is_no_in_range_error("prime", left, right);
2895 }
2896
2897 uint64_t n;
2898 do {
2899 n = next(left, right);
2900 } while (!is_prime(n));
2901 return n;
2902}
2903
2904// O(log^3 (left)) expected.
2905// left <= 2^64 - 59.
2906inline uint64_t prime_from(uint64_t left) {
2907 tgen_ensure(left <= std::numeric_limits<uint64_t>::max() - 58,
2908 "math: invalid bound");
2909 for (uint64_t i = std::max<uint64_t>(2, left);; ++i)
2910 if (is_prime(i))
2911 return i;
2912}
2913
2914// O(log^3 (right)) expected.
2915inline uint64_t prime_upto(uint64_t right) {
2916 if (right >= 2)
2917 for (uint64_t i = right; i >= 2; --i)
2918 if (is_prime(i))
2919 return i;
2920 throw detail::there_is_no_upto_error("prime", right);
2921}
2922
2923// O(n^(1/4) log n) expected.
2924// 0 < n.
2925inline int num_divisors(uint64_t n) {
2926 int divisors = 1;
2927 for (auto [p, e] : factor_by_prime(n))
2928 divisors *= (e + 1);
2929 return divisors;
2930}
2931
2932// Random number in [left, right] with `divisor_count` divisors.
2933// O(log(right) log(divisor_count)).
2934// divisor_count must be prime.
2935inline uint64_t gen_divisor_count(uint64_t left, uint64_t right,
2936 int divisor_count) {
2937 tgen_ensure(divisor_count > 0 and is_prime(divisor_count),
2938 "math: divisor count must be prime");
2939 int root = divisor_count - 1;
2940 uint64_t lo = detail::kth_root_floor(left, root);
2941 if (*detail::expo(lo, root, left) < left)
2942 ++lo;
2943 uint64_t p = gen_prime(lo, detail::kth_root_floor(right, root));
2944 return *detail::expo(p, root, right);
2945}
2946
2947// O(|mods| + log (right)).
2948// |rems| = |mods|.
2949// rems_i < mods_i.
2950inline uint64_t gen_congruent(uint64_t left, uint64_t right,
2951 std::vector<uint64_t> rems,
2952 std::vector<uint64_t> mods) {
2953 if (left > right)
2954 throw detail::there_is_no_in_range_error("congruent number", left,
2955 right);
2956 tgen_ensure(rems.size() == mods.size(),
2957 "math: number of remainders and mods must be the same");
2958 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
2959
2960 detail::crt crt;
2961 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
2962 tgen_ensure(rems[i] < mods[i],
2963 "math: remainder must be smaller than the mod");
2964 crt = crt * detail::crt(rems[i], mods[i]);
2965
2966 if (crt.a == -1)
2967 throw detail::there_is_no_in_range_error("congruent number", left,
2968 right);
2969 if (crt.m > right) {
2970 if (!(left <= crt.a and crt.a <= right))
2971 throw detail::there_is_no_in_range_error("congruent number",
2972 left, right);
2973
2974 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
2975 if (crt.a % mods[j] != rems[j])
2976 throw detail::there_is_no_in_range_error("congruent number",
2977 left, right);
2978 return crt.a;
2979 }
2980 }
2981
2982 uint64_t k_min = crt.a >= left ? 0 : ((left - crt.a) + crt.m - 1) / crt.m;
2983 uint64_t k_max = (right - crt.a) / crt.m;
2984
2985 if (k_min > k_max)
2986 throw detail::there_is_no_in_range_error("congruent number", left,
2987 right);
2988
2989 return crt.a + next(k_min, k_max) * crt.m;
2990}
2991
2992// O(log (right)).
2993// rem < mod.
2994inline uint64_t gen_congruent(uint64_t left, uint64_t right, uint64_t rem,
2995 uint64_t mod) {
2996 return gen_congruent(left, right, std::vector<uint64_t>({rem}),
2997 std::vector<uint64_t>({mod}));
2998}
2999
3000// First congruent number >= left.
3001// O(|mods| + log (left)).
3002// |rems| = |mods|.
3003// rems_i < mods_i.
3004inline uint64_t congruent_from(uint64_t left, std::vector<uint64_t> rems,
3005 std::vector<uint64_t> mods) {
3006 tgen_ensure(rems.size() == mods.size(),
3007 "math: number of remainders and mods must be the same");
3008 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
3009
3010 detail::crt crt;
3011 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
3012 tgen_ensure(rems[i] < mods[i],
3013 "math: remainder must be smaller than the mod");
3014 crt = crt * detail::crt(rems[i], mods[i]);
3015
3016 if (crt.a == -1)
3017 throw detail::there_is_no_from_error("congruent number", left);
3018 if (crt.m > std::numeric_limits<uint64_t>::max()) {
3019 if (crt.a < left)
3020 throw detail::error(
3021 "math: congruent number does not exist or is too large");
3022
3023 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
3024 if (crt.a % mods[j] != rems[j])
3025 throw detail::error("math: congruent number does "
3026 "not exist or is too large");
3027 return crt.a;
3028 }
3029 }
3030
3031 uint64_t k = 0;
3032 if (crt.a < left)
3033 k = ((left - crt.a) + crt.m - 1) / crt.m;
3034 detail::i128 result = crt.a + k * crt.m;
3035
3036 if (result > std::numeric_limits<uint64_t>::max())
3037 throw detail::error("math: congruent number is too large");
3038 return result;
3039}
3040
3041// O(log (left))
3042// rem < mod.
3043inline uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod) {
3044 return congruent_from(left, std::vector<uint64_t>{rem},
3045 std::vector<uint64_t>{mod});
3046}
3047
3048// Last congruent number <= right.
3049// O(|mods| + log (right)).
3050// |rems| = |mods|.
3051// rems_i < mods_i.
3052inline uint64_t congruent_upto(uint64_t right, std::vector<uint64_t> rems,
3053 std::vector<uint64_t> mods) {
3054 tgen_ensure(rems.size() == mods.size(),
3055 "math: number of remainders and mods must be the same");
3056 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
3057
3058 detail::crt crt;
3059 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
3060 tgen_ensure(rems[i] < mods[i],
3061 "math: remainder must be smaller than the mod");
3062
3063 crt = crt * detail::crt(rems[i], mods[i]);
3064
3065 if (crt.a == -1)
3066 throw detail::there_is_no_upto_error("congruent number", right);
3067 if (crt.m > right) {
3068 if (!(crt.a <= right))
3069 throw detail::there_is_no_upto_error("congruent number", right);
3070
3071 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
3072 if (crt.a % mods[j] != rems[j])
3073 throw detail::there_is_no_upto_error("congruent number",
3074 right);
3075 return crt.a;
3076 }
3077 }
3078
3079 if (crt.a > right)
3080 throw detail::there_is_no_upto_error("congruent number", right);
3081
3082 uint64_t k = (right - crt.a) / crt.m;
3083 detail::i128 result = crt.a + k * crt.m;
3084
3085 if (result < 0)
3086 throw detail::there_is_no_upto_error("congruent number", right);
3087 return result;
3088}
3089
3090// O(log r)
3091// rem < mod.
3092inline uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod) {
3093 return congruent_upto(right, std::vector<uint64_t>{rem},
3094 std::vector<uint64_t>{mod});
3095}
3096
3097// Mod used for FFT/NTT.
3098inline constexpr int FFT_MOD = 998244353;
3099
3100// Fibonacci sequence up to 2^64.
3101inline const std::vector<uint64_t> &fibonacci() {
3102 static const std::vector<uint64_t> fib = [] {
3103 std::vector<uint64_t> v = {0, 1};
3104 while (v.back() <=
3105 std::numeric_limits<uint64_t>::max() - v[v.size() - 2])
3106 v.push_back(v.back() + v[v.size() - 2]);
3107 return v;
3108 }();
3109 return fib;
3110}
3111
3112// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3113// O(n).
3114// 0 < n.
3115// 0 < part_left.
3116inline std::vector<int>
3117gen_partition(int n, int part_left = 1,
3118 std::optional<int> part_right = std::nullopt) {
3119 if (!part_right.has_value())
3120 part_right = n;
3121 part_right = std::min(*part_right, n);
3122 tgen_ensure(n > 0 and part_left > 0,
3123 "math: invalid parameters to gen_partition");
3124 tgen_ensure(part_left <= n and *part_right > 0, "math: no such partition");
3125
3126 // dp[i] = log(number of ways to add to i).
3127 std::vector<long double> dp(n + 1, detail::LOG_ZERO);
3128 dp[0] = detail::LOG_ONE;
3129 long double window = detail::LOG_ZERO;
3130 for (int i = 1; i <= n; ++i) {
3131 if (i >= part_left)
3132 window = detail::add_log_space(window, dp[i - part_left]);
3133 if (i >= *part_right + 1)
3134 window = detail::sub_log_space(window, dp[i - *part_right - 1]);
3135 dp[i] = window;
3136 }
3137 tgen_ensure(dp[n] >= 0, "math: no such partition");
3138
3139 // Crazy math tricks ahead.
3140 auto dp_pref = dp;
3141 for (int i = 1; i <= n; ++i)
3142 dp_pref[i] = detail::add_log_space(dp_pref[i - 1], dp[i]);
3143
3144 std::vector<int> part;
3145 int sum = n;
3146 while (sum > 0) {
3147 // Will generate a number such that what remains is in [l, r].
3148 int l = std::max(0, sum - *part_right), r = sum - part_left;
3149 detail::tgen_ensure_against_bug(r >= 0, "math: r < 0 in gen_partition");
3150
3151 int nxt_sum = std::min(sum, r);
3152 long double random = next<long double>(0, 1);
3153
3154 // We generate a value X (log space), and then choose nxt_sum such
3155 // that dp_pref[nxt_sum-1] < X <= dp_pref[nxt_sum].
3156
3157 // Math hack:
3158 // Let A = pref[l-1], B = pref[r], U = rand().
3159 // X = log[exp(A) + U * (exp(B) - exp(A))]
3160 // = log{exp(B) * [exp(A) / exp(B) + U * (1 - exp(A) / exp(B))]}
3161 // = B + log[exp(A - B) + U - U * exp(A - B))]
3162 // = B + log[U + (1 - U) * exp(A - B)].
3163 long double val_l = l ? dp_pref[l - 1] : detail::LOG_ZERO,
3164 val_r = dp_pref[r];
3165 while (nxt_sum > l and
3166 dp_pref[nxt_sum - 1] >=
3167 val_r + detail::log_space(random +
3168 (1 - random) * exp(val_l - val_r)))
3169 --nxt_sum;
3170
3171 part.push_back(sum - nxt_sum);
3172 sum = nxt_sum;
3173 }
3174
3175 return part;
3176}
3177
3178// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3179// O(n) time/memory if part_right is not set, O(n * k) time/memory otherwise.
3180// 0 < k <= n.
3181// 0 <= part_left.
3182inline std::vector<int>
3183gen_partition_fixed_size(int n, int k, int part_left = 0,
3184 std::optional<int> part_right = std::nullopt) {
3185 if (!part_right.has_value())
3186 part_right = n;
3187 part_right = std::min(*part_right, n);
3188 tgen_ensure(0 < k and k <= n and part_left >= 0,
3189 "math: invalid parameters to gen_partition_fixed_size");
3190 tgen_ensure(static_cast<long long>(k) * part_left <= n and
3191 n <= static_cast<long long>(k) * (*part_right),
3192 "math: no such partition");
3193
3194 // What we need to distribute to the parts.
3195 int s = n - k * part_left;
3196
3197 std::vector<int> part(k);
3198 if (*part_right == n) {
3199 // Stars and bars - O(n).
3200 std::vector<int> cuts = {-1};
3201
3202 int total = s + k - 1, bars = k - 1;
3203 for (int i = 0; i < total and bars > 0; ++i)
3204 if (next<long double>(0, 1) <
3205 static_cast<long double>(bars) / (total - i)) {
3206 cuts.push_back(i);
3207 --bars;
3208 }
3209 cuts.push_back(total);
3210
3211 // Recovers parts.
3212 for (int i = 0; i < k; ++i)
3213 part[i] = cuts[i + 1] - cuts[i] - 1;
3214 } else {
3215 // DP with log trick - O(nk).
3216 int u = *part_right - part_left;
3217
3218 // dp[i][j] = log(#ways to fill i parts with sum j)
3219 std::vector<std::vector<long double>> dp(
3220 k + 1, std::vector<long double>(s + 1, detail::LOG_ZERO));
3221 dp[0][0] = detail::LOG_ONE;
3222
3223 for (int i = 1; i <= k; ++i) {
3224 std::vector<long double> pref = dp[i - 1];
3225 for (int j = 1; j <= s; ++j)
3226 pref[j] = detail::add_log_space(pref[j - 1], dp[i - 1][j]);
3227
3228 for (int j = 0; j <= s; ++j) {
3229 dp[i][j] = pref[j];
3230 if (j >= u + 1)
3231 dp[i][j] = detail::sub_log_space(dp[i][j], pref[j - u - 1]);
3232 }
3233 }
3234
3235 // Recovers parts backwards.
3236 int left_to_distribute = s;
3237 for (int i = k; i >= 1; --i) {
3238 long double log_total = detail::LOG_ZERO;
3239 for (int j = 0; j <= u and j <= left_to_distribute; ++j)
3240 log_total = detail::add_log_space(
3241 log_total, dp[i - 1][left_to_distribute - j]);
3242 detail::tgen_ensure_against_bug(
3243 log_total != detail::LOG_ZERO,
3244 "math: total == 0 in gen_partition_fixed_size");
3245
3246 // Now we choose a number with probability proportional to
3247 // dp[i-1][.].
3248
3249 // log(rand() * total) = log(rand()) + log(total).
3250 long double random =
3251 detail::log_space(next<long double>(0, 1)) + log_total;
3252
3253 long double cur_prob = detail::LOG_ZERO;
3254 int chosen = 0;
3255 for (int j = 0; j <= u and j <= left_to_distribute; ++j) {
3256 cur_prob = detail::add_log_space(
3257 cur_prob, dp[i - 1][left_to_distribute - j]);
3258 if (random < cur_prob) {
3259 chosen = j;
3260 break;
3261 }
3262 }
3263
3264 part[k - i] = chosen;
3265 left_to_distribute -= chosen;
3266 }
3267 }
3268
3269 for (int &i : part)
3270 i += part_left;
3271 return part;
3272}
3273
3274// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3275// Inspired by jngen rndm.partition: random delimiters, sort, gap recovery;
3276// omits jngen's part reordering, shuffles, and two-pass redistribution.
3277// 0 < k <= n.
3278// 0 <= part_left.
3279// Not uniformly random; optimized for speed.
3280// O(k log k).
3282 uint64_t n, int k, uint64_t part_left = 0,
3283 std::optional<uint64_t> part_right = std::nullopt) {
3284 if (!part_right.has_value())
3285 part_right = n;
3286 part_right = std::min(*part_right, n);
3287
3288 detail::u128 n128 = n;
3289 detail::u128 k128 = k;
3290 detail::u128 part_left128 = part_left;
3291 detail::u128 part_right128 = *part_right;
3292
3293 tgen_ensure(k > 0 and k128 <= n128,
3294 "math: invalid parameters to gen_partition_fixed_size_fast");
3295 tgen_ensure(part_right128 >= part_left128 and
3296 k128 * part_left128 <= n128 and
3297 k128 * part_right128 >= n128,
3298 "math: no such partition");
3299
3300 uint64_t slack_total = n128 - k128 * part_left128;
3301 uint64_t slack_max = part_right128 - part_left128;
3302
3303 std::vector<uint64_t> part(k);
3304 if (k == 1) {
3305 part[0] = slack_total;
3306 } else {
3307 std::vector<uint64_t> cuts(k - 1);
3308 for (uint64_t &d : cuts)
3309 d = next<uint64_t>(0, slack_total);
3310 std::sort(cuts.begin(), cuts.end());
3311
3312 uint64_t prev = 0;
3313 for (int i = 0; i + 1 < k; ++i) {
3314 part[i] = cuts[i] - prev;
3315 prev = cuts[i];
3316 }
3317 part[k - 1] = slack_total - prev;
3318 }
3319
3320 auto add_part_left = [part_left](uint64_t x) -> uint64_t {
3321 detail::u128 val = x + part_left;
3322 detail::tgen_ensure_against_bug(
3323 val <= std::numeric_limits<uint64_t>::max(),
3324 "math: part + part_left exceeds uint64_t in "
3325 "gen_partition_fixed_size_fast");
3326 return val;
3327 };
3328
3329 if (slack_max >= slack_total) {
3330 for (uint64_t &x : part)
3331 x = add_part_left(x);
3332 return part;
3333 }
3334
3335 detail::u128 remaining = 0;
3336 for (uint64_t &x : part) {
3337 if (x > slack_max) {
3338 remaining += x - slack_max;
3339 x = slack_max;
3340 }
3341 x = add_part_left(x);
3342 }
3343
3344 if (remaining > 0) {
3345 for (uint64_t &x : part) {
3346 if (x < *part_right && remaining > 0) {
3347 detail::u128 room = *part_right - x;
3348 detail::u128 add = std::min(remaining, room);
3349 detail::u128 val = x + add;
3350 detail::tgen_ensure_against_bug(
3351 val <= *part_right,
3352 "math: part exceeds part_right after redistribution in "
3353 "gen_partition_fixed_size_fast");
3354 x = val;
3355 remaining -= add;
3356 }
3357 }
3358 detail::tgen_ensure_against_bug(
3359 remaining == 0, "math: remaining mass after redistribution in "
3360 "gen_partition_fixed_size_fast");
3361 }
3362
3363 return part;
3364}
3365
3366// Random partition of elements into k ordered groups (input order preserved).
3367// If max_size is unset, part sizes are uniform via gen_partition_fixed_size.
3368// If max_size is set, uses gen_partition_fixed_size_fast (not uniform).
3369// O(n) if max_size is unset; O(n + k log k) if max_size is set.
3370template <typename T>
3371std::vector<std::vector<T>>
3372partition_elements(std::vector<T> elements, int k, int min_size = 0,
3373 std::optional<uint64_t> max_size = std::nullopt) {
3374 size_t n = elements.size();
3375 tgen_ensure(k > 0, "math: partition_elements: k must be positive");
3376 tgen_ensure(min_size >= 0,
3377 "math: partition_elements: min_size must be non-negative");
3378
3379 std::vector<uint64_t> sizes;
3380 if (max_size.has_value()) {
3381 sizes = gen_partition_fixed_size_fast(n, k, min_size, max_size);
3382 } else {
3383 for (int sz : gen_partition_fixed_size(n, k, min_size))
3384 sizes.push_back(sz);
3385 }
3386
3387 std::vector<std::vector<T>> groups;
3388 groups.reserve(k);
3389 size_t pos = 0;
3390 for (uint64_t sz : sizes) {
3391 groups.emplace_back(elements.begin() + pos,
3392 elements.begin() + pos + sz);
3393 pos += sz;
3394 }
3395 return groups;
3396}
3397
3398}; // namespace math
3399
3400/**************
3401 * *
3402 * STRING *
3403 * *
3404 **************/
3405
3406namespace detail {
3407
3408/*
3409 * Regex.
3410 *
3411 * Compatible with testlib's regex.
3412 *
3413 * Operations:
3414 * - A single character yields itself ("a", "3").
3415 * - A list of characters inside square braces yields any a random element
3416 * from the list ("[abc123]").
3417 * - A range of characters is equivalent to listing them ("[a-z1-9A-Z]").
3418 * - A pattern followed by {n} yields the pattern repeated n times ("a{3}").
3419 * - A pattern followed by {l,r} yields the pattern repeated between l and r
3420 * times, uniformly at random ("a{3,5}").
3421 * - A list of patterns separated by | yields a random pattern from the
3422 * list, uniformly at random ("abc|def|ghi").
3423 * - Parentheses can be used for grouping ("a((a|b){3})").
3424 *
3425 * Examples:
3426 * 1. str("[1-9][0-9]{1,2}") generates two- or three-digit numbers.
3427 * 2. str("a[b-d]{2}|e") generates "e" or a random string of length 3, with
3428 * the first character being 'a' and the second and
3429 * third characters being 'b', 'c', or 'd'.
3430 * 3. str("[1-9][0-9]{%d}", n-1) generates n-digit numbers.
3431 *
3432 * Operations defined by {n} and {l,r} are applied from left to right, and
3433 * the pattern that comes before has its delimiters defined either by () or
3434 * [] at its end or is taken from the beginning of the pattern (in
3435 * "a[bc]{2}", "{2}" is applied to "[bc]", and in "[01]abc{3}", the "{3}" is
3436 * applied to "[01]abc").
3437 */
3438
3439// If it has children, it is either a SEQ or an OR group, defined by the
3440// pattern_ field.
3441struct regex_node {
3442 // Considered to be repetition of left_bound != -1, pattern if
3443 // children_.empty(), otherwise "SEQ" or "OR", defined by the pattern_
3444 // field.
3445 std::string
3446 pattern_; // Either pattern, or "SEQ" or "OR" (if !children_.empty()).
3447 std::vector<regex_node> children_; // Children, when SEQ or OR.
3448 int left_bound_, right_bound_; // Left and right bounds of the repetition,
3449 // or -1 if not a repetition.
3450 double
3451 log_space_num_ways_; // Log space number of ways to match the pattern.
3452 std::optional<distinct_container<char>>
3453 distinct_; // Distinct generator for the pattern, for [chars].
3454
3455 // c or [chars].
3456 regex_node(const std::string &pattern)
3457 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3458 if (pattern.size() == 1) {
3459 log_space_num_ways_ = math::detail::LOG_ONE;
3460 return;
3461 }
3462 tgen_ensure_against_bug(pattern[0] == '[' and pattern.back() == ']',
3463 "str: invalid regex: expected character class");
3464 int size = pattern.size() - 2;
3465 log_space_num_ways_ = math::detail::log_space(size);
3466 distinct_ = distinct_container<char>(pattern.substr(1, size));
3467 }
3468 // SEQ or OR.
3469 regex_node(const std::string &pattern, std::vector<regex_node> &children)
3470 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3471 if (pattern == "SEQ") {
3472 // Multiply the number of ways.
3473 log_space_num_ways_ = math::detail::LOG_ONE;
3474 for (const auto &child : children)
3475 log_space_num_ways_ += child.log_space_num_ways_;
3476 } else if (pattern == "OR") {
3477 // Add the number of ways.
3478 log_space_num_ways_ = math::detail::LOG_ZERO;
3479 for (const auto &child : children)
3480 log_space_num_ways_ = math::detail::add_log_space(
3481 log_space_num_ways_, child.log_space_num_ways_);
3482 } else
3483 tgen_ensure_against_bug("str: invalid regex: expected SEQ or OR");
3484
3485 children_ = std::move(children);
3486 children.clear();
3487 }
3488 // REP.
3489 regex_node(int left_bound, int right_bound, regex_node &child)
3490 : pattern_("REP"), left_bound_(left_bound), right_bound_(right_bound) {
3491 log_space_num_ways_ = math::detail::LOG_ZERO;
3492 for (int i = left_bound; i <= right_bound; ++i)
3493 log_space_num_ways_ = math::detail::add_log_space(
3494 log_space_num_ways_, i * child.log_space_num_ways_);
3495
3496 children_.push_back(std::move(child));
3497 }
3498};
3499
3500// State of the regex parser.
3501struct regex_state {
3502 std::vector<regex_node> cur; // Current sequence of nodes.
3503 std::vector<regex_node> branches; // Branches of the current OR group.
3504};
3505
3506// Creates a SEQ node from the current state.
3507inline regex_node make_regex_seq(regex_state &st) {
3508 return regex_node("SEQ", st.cur);
3509}
3510
3511// Finishes current state.
3512inline regex_node finish_regex_state(regex_state &st) {
3513 // SEQ.
3514 if (st.branches.empty())
3515 return make_regex_seq(st);
3516
3517 // OR.
3518 st.branches.push_back(make_regex_seq(st));
3519 return regex_node("OR", st.branches);
3520}
3521
3522// Parses a regex pattern into a tree, computing the number of ways to match the
3523// pattern.
3524inline regex_node parse_regex(std::string regex) {
3525 std::string new_regex;
3526 for (char c : regex)
3527 if (c != ' ')
3528 new_regex += c;
3529 swap(regex, new_regex);
3530 regex_state cur;
3531 std::vector<regex_state> stack;
3532
3533 for (size_t i = 0; i < regex.size(); ++i) {
3534 char c = regex[i];
3535
3536 if (c == '(') {
3537 // Pushes the current state to the stack.
3538 stack.push_back(std::move(cur));
3539 cur = regex_state();
3540 } else if (c == ')') {
3541 // Finishes the current state, and adds it to the parent.
3542 regex_node node = finish_regex_state(cur);
3543
3544 tgen_ensure(!stack.empty(), "str: invalid regex: unmatched `)`");
3545 cur = std::move(stack.back());
3546 stack.pop_back();
3547
3548 cur.cur.push_back(std::move(node));
3549 } else if (c == '|') {
3550 // Starts a new OR group.
3551 regex_node node = make_regex_seq(cur);
3552 cur.branches.push_back(std::move(node));
3553 } else if (c == '[') {
3554 // Parses a character class.
3555 std::string chars;
3556
3557 for (++i; i < regex.size() and regex[i] != ']'; ++i) {
3558 if (i + 2 < regex.size() and regex[i + 1] == '-') {
3559 char a = regex[i], b = regex[i + 2];
3560 if (a > b)
3561 std::swap(a, b);
3562 for (char x = a; x <= b; ++x)
3563 chars += x;
3564 i += 2;
3565 } else
3566 chars += regex[i];
3567 }
3568
3569 tgen_ensure(i < regex.size() and regex[i] == ']',
3570 "str: invalid regex: unmatched `[`");
3571 cur.cur.emplace_back("[" + chars + "]");
3572 } else if (c == '{') {
3573 // Parses a repetition.
3574 ++i;
3575 int l = -1, r = -1;
3576
3577 while (i < regex.size() and
3578 isdigit(static_cast<unsigned char>(regex[i]))) {
3579 if (l == -1)
3580 l = 0;
3581 tgen_ensure(l <= static_cast<int>(1e8),
3582 "str: invalid regex: number too large inside `{}`");
3583 l = 10 * l + (regex[i] - '0');
3584 ++i;
3585 }
3586
3587 if (i < regex.size() and regex[i] == ',') {
3588 ++i;
3589 while (i < regex.size() and
3590 isdigit(static_cast<unsigned char>(regex[i]))) {
3591 if (r == -1)
3592 r = 0;
3594 r <= static_cast<int>(1e8),
3595 "str: invalid regex: number too large inside `{}`");
3596 r = 10 * r + (regex[i] - '0');
3597 ++i;
3598 }
3599 } else
3600 r = l;
3601
3602 tgen_ensure(i < regex.size() and regex[i] == '}',
3603 "str: invalid regex: unmatched `{`");
3604 tgen_ensure(l != -1 and r != -1,
3605 "str: invalid regex: missing number inside `{}`");
3606 tgen_ensure(l <= r,
3607 "str: invalid regex: invalid range inside `{}`");
3608
3609 // Creates a REP node from the previous node.
3610 tgen_ensure(!cur.cur.empty(),
3611 "str: invalid regex: expected expression before `{}`");
3612
3613 regex_node rep(l, r, cur.cur.back());
3614 cur.cur.pop_back();
3615 cur.cur.push_back(std::move(rep));
3616 } else {
3617 // Creates a char node.
3618 cur.cur.emplace_back(std::string(1, c));
3619 }
3620 }
3621
3622 tgen_ensure(stack.empty(), "str: invalid regex: unmatched `(`");
3623 return finish_regex_state(cur);
3624}
3625
3626// Generates a uniformly random string that matches the given regex.
3627inline void gen_regex(const regex_node &node, std::string &str) {
3628 // For [chars], generate a random character from the list.
3629 if (node.pattern_[0] == '[') {
3630 str += node.pattern_[1 + next<int>(0, node.pattern_.size() - 3)];
3631 return;
3632 }
3633
3634 // For REP, generate a random number of times to repeat the pattern.
3635 if (node.left_bound_ != -1) {
3636 // Generates a random value W from 0 to num_ways.
3637 // log(W) = log(random(0, 1) * num_ways)
3638 // = log(random(0, 1)) + log(num_ways).
3639 double log_rand = math::detail::log_space(next<double>(0, 1)) +
3640 node.log_space_num_ways_;
3641 double cur_prob = math::detail::LOG_ZERO;
3642 double child_num_ways = node.children_[0].log_space_num_ways_;
3643
3644 for (int i = node.left_bound_; i <= node.right_bound_; ++i) {
3645 cur_prob =
3646 math::detail::add_log_space(cur_prob, i * child_num_ways);
3647 if (log_rand <= cur_prob) {
3648 for (int j = 0; j < i; ++j)
3649 gen_regex(node.children_[0], str);
3650 return;
3651 }
3652 }
3653
3654 tgen_ensure_against_bug(false,
3655 "str: log_rand > cur_prob in REP gen_regex");
3656 }
3657
3658 // For SEQ, generate all children.
3659 if (!node.children_.empty() and node.pattern_ == "SEQ") {
3660 for (const regex_node &child : node.children_)
3661 gen_regex(child, str);
3662 return;
3663 }
3664
3665 // For OR, generate a random child.
3666 if (!node.children_.empty() and node.pattern_ == "OR") {
3667 // Generates a random value W from 0 to num_ways.
3668 // log(W) = log(random(0, 1) * num_ways)
3669 // = log(random(0, 1)) + log(num_ways).
3670 double log_rand = math::detail::log_space(next<double>(0, 1)) +
3671 node.log_space_num_ways_;
3672 double cur_prob = math::detail::LOG_ZERO;
3673
3674 for (const regex_node &child : node.children_) {
3675 cur_prob = math::detail::add_log_space(cur_prob,
3676 child.log_space_num_ways_);
3677 if (log_rand <= cur_prob) {
3678 gen_regex(child, str);
3679 return;
3680 }
3681 }
3682
3683 tgen_ensure_against_bug(false,
3684 "str: log_rand > cur_prob in OR gen_regex");
3685 }
3686
3687 // For char, generate the character.
3688 detail::tgen_ensure_against_bug(
3689 node.pattern_.size() == 1,
3690 "str: invalid regex: expected single character, but got `" +
3691 node.pattern_ + "`");
3692 str += node.pattern_[0];
3693}
3694
3695// Formats a regex string with given arguments.
3696template <typename... Args>
3697std::string regex_format(const std::string &s, Args &&...args) {
3698 if constexpr (sizeof...(Args) == 0) {
3699 return s;
3700 } else {
3701 int size = std::snprintf(nullptr, 0, s.c_str(), args...) + 1;
3702 std::string buf(size, '\0');
3703 std::snprintf(buf.data(), size, s.c_str(), args...);
3704 buf.pop_back(); // remove '\0'
3705 return buf;
3706 }
3707}
3708
3709} // namespace detail
3710
3711/*
3712 * String generator.
3713 */
3714
3715struct str : gen_base<str> {
3716 std::optional<list<char>> list_; // List of characters.
3717 std::optional<detail::regex_node>
3718 root_; // Root node of the regex tree for the whole string.
3719
3720 // Creates generator for strings of size 'size', with random characters in
3721 // [value_left, value_right].
3722 str(int size, char value_left = 'a', char value_right = 'z') {
3723 tgen_ensure(size > 0, "str: size must be positive");
3724 list_ = list<char>(size, value_left, value_right);
3725 }
3726
3727 // Creates generator for strings of size 'size', with random characters in
3728 // 'chars'.
3729 str(int size, std::set<char> chars) {
3730 tgen_ensure(size > 0, "str: size must be positive");
3731 list_ = list<char>(size, chars);
3732 }
3733
3734 // Creates generator for strings that match the given regex.
3735 template <typename... Args> str(const std::string &regex, Args &&...args) {
3736 tgen_ensure(regex.size() > 0, "str: regex must be non-empty");
3737
3738 root_ = detail::parse_regex(
3739 detail::regex_format(regex, std::forward<Args>(args)...));
3740 }
3741
3742 // Restricts strings for str[idx] = value.
3743 str &fix(int idx, char character) {
3744 tgen_ensure(!root_, "str: cannot add restriction for regex");
3745 list_->fix(idx, character);
3746 return *this;
3747 }
3748
3749 // Restricts strings for list[S] to be equal, for given subset S of indices.
3750 str &equal(std::set<int> indices) {
3751 tgen_ensure(!root_, "str: cannot add restriction for regex");
3752 list_->equal(indices);
3753 return *this;
3754 }
3755
3756 // Restricts strings for str[idx_1] = str[idx_2].
3757 str &equal(int idx_1, int idx_2) {
3758 tgen_ensure(!root_, "str: cannot add restriction for regex");
3759 list_->equal(idx_1, idx_2);
3760 return *this;
3761 }
3762
3763 // Restricts strings for str[left..right] to have all equal values.
3764 str &equal_range(int left, int right) {
3765 tgen_ensure(!root_, "str: cannot add restriction for regex");
3766 list_->equal_range(left, right);
3767 return *this;
3768 }
3769
3770 // Restricts strings for all equal chars.
3772 tgen_ensure(!root_, "str: cannot add restriction for regex");
3773 list_->all_equal();
3774 return *this;
3775 }
3776
3777 // Restricts strings for str[left..right] to be a palindrome.
3778 str &palindrome(int left, int right) {
3779 tgen_ensure(!root_, "str: cannot add restriction for regex");
3780 tgen_ensure(0 <= left and left <= right and right < list_->size_,
3781 "str: range indices must be valid");
3782 for (int i = left; i < right - (i - left); ++i)
3783 equal(i, right - (i - left));
3784 return *this;
3785 }
3786
3787 // Restricts strings for the entire string to be a palindrome.
3789 tgen_ensure(!root_, "str: cannot add restriction for regex");
3790 return palindrome(0, list_->size_ - 1);
3791 }
3792
3793 // Restricts strings for str[S] to be different (distinct), for given subset
3794 // S of indices.
3795 str &different(std::set<int> indices) {
3796 tgen_ensure(!root_, "str: cannot add restriction for regex");
3797 list_->different(indices);
3798 return *this;
3799 }
3800
3801 // Restricts strings for str[idx_1] != str[idx_2].
3802 str &different(int idx_1, int idx_2) {
3803 tgen_ensure(!root_, "str: cannot add restriction for regex");
3804 list_->different(idx_1, idx_2);
3805 return *this;
3806 }
3807
3808 // Restricts lists for list[left..right] to have all different chars.
3809 str &different_range(int left, int right) {
3810 tgen_ensure(!root_, "str: cannot add restriction for regex");
3811 list_->different_range(left, right);
3812 return *this;
3813 }
3814
3815 // Restricts strings for all chars to be different.
3817 tgen_ensure(!root_, "str: cannot add restriction for regex");
3818 list_->all_different();
3819 return *this;
3820 }
3821
3822 // Restricts adjacent characters to be different: str[i] != str[i+1].
3824 tgen_ensure(!root_, "str: cannot add restriction for regex");
3825 list_->adjacent_different();
3826 return *this;
3827 }
3828
3829 // str value.
3831 using tgen_is_sequential_tag = detail::is_sequential_tag;
3832
3833 using value_type = char;
3834 using std_type = std::string;
3835 std::string str_;
3836
3837 value(const std::string &str) : str_(str) {
3838 tgen_ensure(!str_.empty(), "str: value: cannot be empty");
3839 }
3840
3841 // Fetches size.
3842 int size() const { return str_.size(); }
3843
3844 // Fetches position idx.
3845 char &operator[](int idx) {
3846 tgen_ensure(0 <= idx and idx < size(),
3847 "str: value: index out of bounds");
3848 return str_[idx];
3849 }
3850 const char &operator[](int idx) const {
3851 tgen_ensure(0 <= idx and idx < size(),
3852 "str: value: index out of bounds");
3853 return str_[idx];
3854 }
3855
3856 // Sorts characters in non-decreasing order.
3857 // O(n log n).
3859 std::sort(str_.begin(), str_.end());
3860 return *this;
3861 }
3862
3863 // Reverses string.
3864 // O(n).
3866 std::reverse(str_.begin(), str_.end());
3867 return *this;
3868 }
3869
3870 // Lowercases all characters.
3871 // O(n).
3873 for (char &c : str_)
3874 c = std::tolower(c);
3875 return *this;
3876 }
3877
3878 // Uppercases all characters.
3879 // O(n).
3881 for (char &c : str_)
3882 c = std::toupper(c);
3883 return *this;
3884 }
3885
3886 // Concatenates two values.
3887 // Linear.
3888 value operator+(const value &rhs) const {
3889 return value(str_ + rhs.str_);
3890 }
3891
3892 // Shuffles string uniformly.
3893 // O(n).
3895 for (int i = 0; i < size(); ++i)
3896 std::swap(str_[i], str_[next(0, size() - 1)]);
3897 return *this;
3898 }
3899
3900 // Returns a random character uniformly.
3901 // O(1).
3902 char pick() const { return str_[next<int>(0, size() - 1)]; }
3903
3904 // Returns str_[i] with probability proportional to distribution[i].
3905 // O(1).
3906 template <typename Dist>
3907 char pick_by_distribution(const std::vector<Dist> &distribution) const {
3908 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
3909 "value and distribution must have the same size");
3910 return str_[next_by_distribution(distribution)];
3911 }
3912 template <typename Dist>
3913 char pick_by_distribution(
3914 const std::initializer_list<Dist> &distribution) const {
3915 return pick_by_distribution(std::vector<Dist>(distribution));
3916 }
3917
3918 // Chooses k characters uniformly, as in a subsequence of size k.
3919 // O(n).
3920 value choose(int k) const {
3921 tgen_ensure(0 < k and k <= size(),
3922 "number of elements to choose must be valid");
3923 std::string new_str;
3924 int need = k;
3925 for (int i = 0; need > 0; ++i) {
3926 int left = size() - i;
3927 if (next(1, left) <= need) {
3928 new_str.push_back(str_[i]);
3929 need--;
3930 }
3931 }
3932 return value(new_str);
3933 }
3934
3935 // Prints to std::ostream.
3936 friend std::ostream &operator<<(std::ostream &out, const value &val) {
3937 return out << val.str_;
3938 }
3939
3940 // Gets a std::string representing the value.
3941 std::string to_std() const { return std_type(str_); }
3942 };
3943
3944 // Generates str value.
3945 // If created from restrictions: O(n log n).
3946 // If created from regex: expected linear.
3947 value gen() const {
3948 if (root_) {
3949 // Regex.
3950 std::string ret_str;
3951 gen_regex(*root_, ret_str);
3952 return value(ret_str);
3953 } else {
3954 // List.
3955 std::vector<char> vec = list_->gen().to_std();
3956 return value(std::string(vec.begin(), vec.end()));
3957 }
3958 }
3959};
3960
3961/************
3962 * *
3963 * PAIR *
3964 * *
3965 ************/
3966
3967namespace detail {
3968
3969// Generates pair first == second.
3970// O(1).
3971template <typename T> std::pair<T, T> gen_eq(T L1, T R1, T L2, T R2) {
3972 T L = std::max(L1, L2);
3973 T R = std::min(R1, R2);
3974
3975 tgen_ensure(L <= R, "pair: no valid values to generate");
3976 T x = next<T>(L, R);
3977 return {x, x};
3978}
3979
3980// Returns {R1-L1+1, R2-L2+1}.
3981template <typename T>
3982std::pair<u128, u128> get_n_and_m(T L1, T R1, T L2, T R2) {
3983 u128 n = static_cast<i128>(R1) - L1 + 1;
3984 u128 m = static_cast<i128>(R2) - L2 + 1;
3985 return {n, m};
3986}
3987
3988// Returns first + first+1 + ... + last,
3989// num_terms terms. Avoids overflow.
3990static u128 pos_arith_sum(u128 first, u128 last, u128 num_terms) {
3991 u128 x = first + last, y = num_terms;
3992
3993 // x * y / 2, avoiding overflow.
3994 if (x % 2 == 0)
3995 x /= 2;
3996 else
3997 y /= 2;
3998
3999 return x * y;
4000}
4001
4002// Generates pair first != second.
4003// O(1) expected.
4004template <typename T> std::pair<T, T> gen_neq(T L1, T R1, T L2, T R2) {
4005 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4006
4007 T L_intersect = std::max(L1, L2);
4008 T R_intersect = std::min(R1, R2);
4009 u128 inter = static_cast<i128>(R_intersect) - L_intersect + 1;
4010
4011 u128 total = n * m - inter;
4012 tgen_ensure(total > 0, "pair: no valid values to generate");
4013
4014 // Runs O(1) expected times in the worst case.
4015 T a, b;
4016 do {
4017 a = next<T>(L1, R1);
4018 b = next<T>(L2, R2);
4019 } while (a == b);
4020
4021 return {a, b};
4022}
4023
4024// For lt, splits 'second' into two regions:
4025// 1) second <= R1 -> number of 'first' is (second - L1)
4026// 2) second > R1 -> number of 'first' is (R1 - L1 + 1)
4027// Returns {count_region1, count_region2}.
4028// O(1).
4029template <typename T>
4030std::pair<u128, u128> count_lt_regions(T L1, T R1, T L2, T R2) {
4031 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4032
4033 // 'second' must be >= L1 + 1.
4034 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);
4035 i128 R_second = R2;
4036
4037 // Split point for 'second'.
4038 i128 split = std::min<i128>(R_second, R1);
4039
4040 // Region 1: b in [L_second, split].
4041 u128 len1 = std::max<i128>(0, split - L_second + 1);
4042
4043 u128 count_region1 = 0;
4044 if (len1 > 0) {
4045 // For b in [L_second, split], there are (b - L1) ways.
4046 i128 first = L_second - L1;
4047 i128 last = split - L1;
4048
4049 // Arithmetic series first + (first + 1) + ... + last, len1 terms.
4050 count_region1 = pos_arith_sum(first, last, len1);
4051 }
4052
4053 // Region 2: b > R1.
4054 // For b in [R1+1, R_second], there are 'n' ways.
4055 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);
4056
4057 u128 len2 = std::max<i128>(0, R_second - L_second_region2 + 1);
4058 u128 count_region2 = len2 * n;
4059
4060 return {count_region1, count_region2};
4061}
4062
4063// Generates pair first < second.
4064// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4065template <typename T> std::pair<T, T> gen_lt(T L1, T R1, T L2, T R2) {
4066 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4067
4068 // 'second' needs to be at least L1 + 1 to have a valid value for
4069 // 'first'.
4070 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);
4071 i128 R_second = R2;
4072
4073 // Splits 'second' into two regions:
4074 // 1) b <= R1 -> number of 'first' is (b - L1);
4075 // 2) b > R1 -> number of 'first' is (R1 - L1 + 1).
4076 i128 split = std::min<i128>(R_second, R1);
4077
4078 auto [count_region1, count_region2] = count_lt_regions(L1, R1, L2, R2);
4079 u128 total = count_region1 + count_region2;
4080 tgen_ensure(total > 0, "pair: no valid values to generate");
4081
4082 u128 k = detail::next128(total);
4083 if (k < count_region1) {
4084 // Region 1: invert arithmetic series.
4085
4086 // For b in [L_second, split].
4087 u128 len1 = std::max<i128>(0, split - L_second + 1);
4088
4089 // We consider b in [L_second, L_second + d].
4090 // Each b contributes (b - L1) = base + (b - L_second).
4091 // So we sum: base + (base+1) + ... + (base+d)
4092 // d in [0, len1).
4093
4094 i128 base = L_second - L1;
4095 i128 lo = 0, hi = static_cast<i128>(len1) - 1;
4096
4097 while (lo < hi) {
4098 i128 mid = lo + (hi - lo) / 2;
4099
4100 if (pos_arith_sum(base, base + mid, mid + 1) <= k)
4101 lo = mid + 1;
4102 else
4103 hi = mid;
4104 }
4105 i128 d = lo;
4106
4107 // Subtracts prefix sum with d-1 terms from k.
4108 if (d > 0)
4109 k -= pos_arith_sum(base, base + d - 1, d);
4110
4111 return {L1 + static_cast<T>(k), L_second + d};
4112 } else {
4113 // Region 2: uniform block of size n.
4114 k -= count_region1;
4115
4116 // For b in [R1+1, R_second], there are 'n' ways.
4117 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);
4118
4119 return {L1 + static_cast<T>(k % n),
4120 L_second_region2 + static_cast<T>(k / n)};
4121 }
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_gt(T L1, T R1, T L2, T R2) {
4127 auto [first, second] = gen_lt(L2, R2, L1, R1);
4128 return {second, first};
4129}
4130
4131// Generates pair first <= second.
4132// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4133template <typename T> std::pair<T, T> gen_leq(T L1, T R1, T L2, T R2) {
4134 // Counts how many pairs are there with first = second.
4135 i128 L_intersect = std::max(L1, L2);
4136 i128 R_intersect = std::min(R1, R2);
4137 u128 eq_count = std::max<i128>(0, R_intersect - L_intersect + 1);
4138
4139 // Counts how many pairs are there with first < second.
4140 auto [lt_region1, lt_region2] = count_lt_regions(L1, R1, L2, R2);
4141 u128 lt_count = lt_region1 + lt_region2;
4142
4143 u128 total = eq_count + lt_count;
4144 tgen_ensure(total > 0, "pair: no valid values to generate");
4145
4146 if (detail::next128(total) < eq_count)
4147 return gen_eq(L1, R1, L2, R2);
4148 return gen_lt(L1, R1, L2, R2);
4149}
4150
4151// Generates pair first >= second.
4152// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4153template <typename T> std::pair<T, T> gen_geq(T L1, T R1, T L2, T R2) {
4154 auto [first, second] = gen_leq(L2, R2, L1, R1);
4155 return {second, first};
4156}
4157
4158}; // namespace detail
4159
4160/*
4161 * Pair generator.
4162 *
4163 * Pairs of integral types.
4164 */
4165
4166template <typename T> struct pair : gen_base<pair<T>> {
4167 std::pair<T, T> first_, second_; // Range of first and second values.
4168 // Type of restriction.
4169 enum class restriction_type { eq, neq, lt, gt, leq, geq, unspecified };
4170 restriction_type type_ = restriction_type::unspecified;
4171
4172 // Creates a pair with random values in [first_l, first_r] and [second_l,
4173 // second_r].
4174 pair(T first_left, T first_right, T second_left, T second_right)
4175 : first_(first_left, first_right), second_(second_left, second_right) {
4176 tgen_ensure(first_left <= first_right,
4177 "pair: first range must be valid");
4178 tgen_ensure(second_left <= second_right,
4179 "pair: second range must be valid");
4180 }
4181
4182 // Creates a pair with random values in [both_l, both_r].
4183 pair(T both_left, T both_right)
4184 : pair(both_left, both_right, both_left, both_right) {}
4185
4186 // Restricts pair for first = second.
4188 type_ = restriction_type::eq;
4189 return *this;
4190 }
4191
4192 // Restricts pair for first != second.
4194 type_ = restriction_type::neq;
4195 return *this;
4196 }
4197
4198 // Restricts pair for first < second.
4200 type_ = restriction_type::lt;
4201 return *this;
4202 }
4203
4204 // Restricts pair for first > second.
4206 type_ = restriction_type::gt;
4207 return *this;
4208 }
4209
4210 // Restricts pair for first <= second.
4212 type_ = restriction_type::leq;
4213 return *this;
4214 }
4215
4216 // Restricts pair for first >= second.
4218 type_ = restriction_type::geq;
4219 return *this;
4220 }
4221
4222 // Pair value.
4224 using value_type = T;
4225 using std_type = std::pair<T, T>;
4226
4227 std::pair<T, T> pair_;
4228 char sep_;
4229
4230 value(const std::pair<T, T> &pair) : pair_(pair), sep_(' ') {}
4231 value(const T &first, const T &second)
4232 : pair_(first, second), sep_(' ') {}
4233
4234 T first() const { return pair_.first; }
4235 T second() const { return pair_.second; }
4236
4237 // Sets the separator for the pair, for printing.
4238 value &separator(char sep) {
4239 sep_ = sep;
4240 return *this;
4241 }
4242
4243 // Prints to std::ostream, separated by sep_.
4244 friend std::ostream &operator<<(std::ostream &out, const value &val) {
4245 return out << val.pair_.first << val.sep_ << val.pair_.second;
4246 }
4247
4248 // Gets a std::pair representing the value.
4249 auto to_std() const {
4250 if constexpr (!detail::is_generator_value<T>::value) {
4251 return pair_;
4252 } else {
4253 std::pair<typename T::std_type, typename T::std_type> pair(
4254 pair_.first.to_std(), pair_.second.to_std());
4255 return pair;
4256 }
4257 }
4258 };
4259
4260 // Generates a random pair.
4261 // O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4262 value gen() const {
4263 T L1 = first_.first, R1 = first_.second;
4264 T L2 = second_.first, R2 = second_.second;
4265
4266 switch (type_) {
4267 case restriction_type::unspecified:
4268 return {next<T>(L1, R1), next<T>(L2, R2)};
4269 case restriction_type::eq:
4270 return detail::gen_eq<T>(L1, R1, L2, R2);
4271 case restriction_type::neq:
4272 return detail::gen_neq<T>(L1, R1, L2, R2);
4273 case restriction_type::lt:
4274 return detail::gen_lt<T>(L1, R1, L2, R2);
4275 case restriction_type::gt:
4276 return detail::gen_gt<T>(L1, R1, L2, R2);
4277 case restriction_type::leq:
4278 return detail::gen_leq<T>(L1, R1, L2, R2);
4279 case restriction_type::geq:
4280 return detail::gen_geq<T>(L1, R1, L2, R2);
4281 }
4282 throw detail::error("pair: unknown restriction type");
4283 }
4284};
4285
4286/************
4287 * *
4288 * TREE *
4289 * *
4290 ************/
4291
4292namespace detail {
4293
4294// Generates edges from Prufer sequence.
4295// O(n).
4296inline std::vector<std::pair<int, int>> edges_from_prufer(std::vector<int> p) {
4297 int n = p.size() + 2;
4298
4299 // Degrees.
4300 std::vector<int> d(n, 1);
4301 for (int i : p)
4302 d[i]++;
4303
4304 // Adds last vertex.
4305 p.push_back(n - 1);
4306
4307 // Finds first vertex with degree 1.
4308 int idx, u;
4309 idx = u = find(d.begin(), d.end(), 1) - d.begin();
4310
4311 // Generates edges.
4312 std::vector<std::pair<int, int>> edges;
4313 for (int v : p) {
4314 edges.emplace_back(u, v);
4315 if (--d[v] == 1 and v < idx)
4316 u = v;
4317 else
4318 idx = u = find(d.begin() + idx + 1, d.end(), 1) - d.begin();
4319 }
4320 return edges;
4321}
4322
4323// Disjoint set union (union-find) for connectivity queries.
4324struct dsu {
4325 std::vector<int> parent_;
4326 std::vector<unsigned char> rank_;
4327
4328 // Creates a dsu with `n` elements, indexed from 0 to n-1.
4329 // Initially every element is in its own set.
4330 // O(n).
4331 dsu(int n) : parent_(n), rank_(n, 0) {
4332 for (int i = 0; i < n; ++i)
4333 parent_[i] = i;
4334 }
4335
4336 // Adds new elements to the dsu, each in their own new set.
4337 // O(k) amortized.
4338 void add_elements(int k) {
4339 for (int i = 0; i < k; ++i) {
4340 int new_id = parent_.size();
4341 parent_.push_back(new_id);
4342 rank_.push_back(0);
4343 }
4344 }
4345
4346 // Finds representative of set containing i.
4347 // O(alpha(n)) amortized, O(log n) worst case.
4348 int find(int i) {
4349 return parent_[i] == i ? i : parent_[i] = find(parent_[i]);
4350 }
4351
4352 // Merges components of `a` and `b`. Returns if the sets were united, and
4353 // false if a and b were in the same set.
4354 // O(alpha(n)) amortized, O(log n) worst case.
4355 bool unite(int a, int b) {
4356 a = find(a);
4357 b = find(b);
4358 if (a == b)
4359 return false;
4360 if (rank_[a] > rank_[b])
4361 std::swap(a, b);
4362 parent_[a] = b;
4363 if (rank_[a] == rank_[b])
4364 ++rank_[b];
4365 return true;
4366 }
4367};
4368
4369} // namespace detail
4370
4371// Forward declaration of wgraph.
4372template <typename VWeight, typename EWeight> struct wgraph;
4373
4374/*
4375 * Tree generator.
4376 *
4377 * Unrooted trees with `n` vertices, indexed from 0 to n-1.
4378 * These are unrooted undirected labeled trees, that is, isomorphism is not
4379 * taken into account. VWeight is the type of vertex weights, and EWeight is
4380 * the type of edge weights. Generator does not generate weights. The weights
4381 * are to be set in the wtree::value.
4382 */
4383
4384template <typename VWeight, typename EWeight>
4385struct wtree : gen_base<wtree<VWeight, EWeight>> {
4386 int n_; // Number of vertices.
4387 std::set<std::pair<int, int>> edges_; // Edges that were set.
4388
4389 // Creates tree generator with `n` vertices.
4390 // O(1).
4391 wtree(int n) : n_(n) {
4392 tgen_ensure(n > 0, "wtree: number of vertices must be positive");
4393 }
4394
4395 // Adds edge between u and v (this edge must be generated).
4396 // O(log n).
4397 wtree &add_edge(int u, int v) {
4398 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,
4399 "wtree: vertices must be indexed in [0, n)");
4400 tgen_ensure(u != v, "wtree: cannot add self loop to tree");
4401
4402 if (u > v)
4403 std::swap(u, v);
4404 edges_.emplace(u, v);
4405 return *this;
4406 }
4407
4408 // Tree value.
4409 //
4410 // Edges are stored in both directions in adjacency list, but only u < v in
4411 // edge list.
4413 using std_type = std::pair<int, std::vector<std::set<int>>>;
4414
4415 int n_; // Number of vertices.
4416 std::vector<std::set<int>> adj_; // Adjacency list.
4417 std::vector<std::pair<int, int>> edges_; // Edge list.
4418 bool print_1_based_; // If should print vertex ids 1-based (print only).
4419 bool print_n_; // If should print n.
4420 std::optional<int> print_parents_; // If should print in parent style
4421 // (stores the root).
4422 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.
4423 std::optional<std::vector<EWeight>>
4424 edge_weights_; // Edge weights (in same order as edges_).
4425 detail::dsu dsu_; // Connectivity of current edges (for cycle checks).
4426
4427 // Creates value from adjacency list.
4428 // O(n).
4429 value(const std::vector<std::set<int>> &adj)
4430 : n_(static_cast<int>(adj.size())), adj_(adj),
4431 print_1_based_(false), print_n_(false), dsu_(n_) {
4432 for (int u = 0; u < n_; ++u)
4433 for (auto v : adj[u]) {
4435 0 <= v and v < n_,
4436 "wtree: value: vertices must be indexed in [0, n)");
4437 // Symmetric adjacency: count each undirected edge once.
4438 if (u < v) {
4439 edges_.emplace_back(u, v);
4441 dsu_.unite(u, v),
4442 "wtree: value: initial graph must form a tree");
4443 }
4444 }
4445 }
4446
4447 // Creates value from `n` and edge list.
4448 // O(n).
4449 value(int n, const std::vector<std::pair<int, int>> &edges)
4450 : n_(n), adj_(n), print_1_based_(false), print_n_(false), dsu_(n) {
4451 edges_.reserve(edges.size());
4452 for (auto [u, v] : edges) {
4453 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n,
4454 "wtree: value: vertices must be indexed in [0, n)");
4455 tgen_ensure(dsu_.unite(u, v),
4456 "wtree: value: initial graph must form a tree");
4457 if (u > v)
4458 std::swap(u, v);
4459 edges_.emplace_back(u, v);
4460 adj_[u].insert(v);
4461 adj_[v].insert(u);
4462 }
4463 }
4464 value(int n, const std::set<std::pair<int, int>> &edges)
4465 : value(n, std::vector<std::pair<int, int>>(edges.begin(),
4466 edges.end())) {}
4467 value(int n, const std::initializer_list<std::pair<int, int>> &edges)
4468 : value(n, std::vector<std::pair<int, int>>(edges)) {}
4469
4470 // Creates tree from graph via Kruskal-like random spanning tree.
4471 // Implemented after wgraph definition.
4472 // O(n + m alpha(n)).
4473 value(const typename wgraph<VWeight, EWeight>::value &g);
4474
4475 // Weight type conversion.
4476 // O(n).
4477 template <typename NewVWeight, typename NewEWeight>
4478 typename wtree<NewVWeight, NewEWeight>::value
4479 convert_weight_types() const {
4480 tgen_ensure(!vertex_weights_.has_value() and
4481 !edge_weights_.has_value(),
4482 "wtree: value: cannot convert weight type after "
4483 "assigning weights");
4484
4485 typename wtree<NewVWeight, NewEWeight>::value new_tree(adj_);
4486 new_tree.print_1_based_ = print_1_based_;
4487 new_tree.print_n_ = print_n_;
4488 new_tree.print_parents_ = print_parents_;
4489 return new_tree;
4490 }
4491
4492 // Fetches number of vertices.
4493 int n() const { return n_; }
4494
4495 // Fetches a const ref. to adjacency list.
4496 const std::vector<std::set<int>> &adj() const { return adj_; }
4497
4498 // Fetches a const ref. to edge list.
4499 const std::vector<std::pair<int, int>> &edges() const { return edges_; }
4500
4501 // Fetches a const ref. to vertex weights.
4503 return vertex_weights_;
4504 }
4505
4506 // Fetches a const ref. to edge weights.
4508 return edge_weights_;
4509 }
4510
4511 // Sets vertex weights.
4512 // O(n).
4513 template <typename NewVWeight = VWeight>
4514 typename wtree<NewVWeight, EWeight>::value set_vertex_weights(
4515 const std::vector<NewVWeight> &vertex_weights) const {
4516 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),
4517 "wtree: value: must give `n` vertex weights");
4518
4519 auto new_tree = convert_weight_types<NewVWeight, EWeight>();
4520 new_tree.vertex_weights_ = vertex_weights;
4521 return new_tree;
4522 }
4523
4524 // Sets edge weights.
4525 // O(n).
4526 template <typename NewEWeight = EWeight>
4527 typename wtree<VWeight, NewEWeight>::value
4528 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {
4530 edge_weights.size() == edges().size(),
4531 "wtree: value: must give `edges().size()` edge weights");
4532
4533 auto new_tree = convert_weight_types<VWeight, NewEWeight>();
4534 new_tree.edge_weights_ = edge_weights;
4535 return new_tree;
4536 }
4537
4538 // Enables edge-weighted mode before adding weighted edges
4539 // incrementally. The tree must have no edges yet. O(1).
4541 tgen_ensure(edges().size() == 0,
4542 "wtree: value: edge_weighted requires a tree with no "
4543 "edges");
4544 tgen_ensure(!edge_weights_.has_value(),
4545 "wtree: value: tree is already edge-weighted");
4546
4547 edge_weights_ = std::vector<EWeight>();
4548 return *this;
4549 }
4550
4551 // Sets that should print vertex ids 1-based. Does not change stored
4552 // ids; use to_std_1_based() for a 1-based export.
4553 // O(1).
4555 print_1_based_ = true;
4556 return *this;
4557 }
4558
4559 // Prints `n` on a new line before printing the tree.
4560 // O(1).
4562 print_n_ = true;
4563 return *this;
4564 }
4565
4566 // Prints the tree in parent style.
4567 // If root = -1, the root is considered to be 0, and its parent is not
4568 // printed. Otherwise, prints the parent of the root as -1. If root = n,
4569 // randomizes the root. O(1).
4570 value &print_parents(int root = -1) {
4571 tgen_ensure(root == -1 or (0 <= root and root < n()) or root == n(),
4572 "wtree: value: root must be -1, `n`, or in [0, n)");
4573 print_parents_ = root;
4574 return *this;
4575 }
4576
4577 // Shuffles the tree's vertex labels (except those in `indices`,
4578 // which keep their current label) and edge order. The change is
4579 // applied eagerly to the underlying adjacency list, edge list,
4580 // vertex weights and edge weights.
4581 // O(n).
4582 value &shuffle_except(std::set<int> indices) {
4583 // Builds the relabeling: for each vertex `i`, `new_label[i]` is
4584 // its new id. Vertices in `indices` keep their label; the others
4585 // are permuted among themselves.
4586 std::vector<int> new_label(n());
4587 std::vector<int> shuffled;
4588 for (int i = 0; i < n(); ++i) {
4589 if (indices.count(i))
4590 new_label[i] = i;
4591 else
4592 shuffled.push_back(i);
4593 }
4594 std::vector<int> targets = shuffled;
4595 tgen::shuffle(targets.begin(), targets.end());
4596 for (size_t k = 0; k < shuffled.size(); ++k)
4597 new_label[shuffled[k]] = targets[k];
4598
4599 // Rewrites adjacency list with new labels.
4600 std::vector<std::set<int>> new_adj(n());
4601 for (int u = 0; u < n(); ++u)
4602 for (int v : adj_[u])
4603 new_adj[new_label[u]].insert(new_label[v]);
4604 adj_ = std::move(new_adj);
4605
4606 // Rewrites edges with new labels (canonical undirected order).
4607 for (auto &[u, v] : edges_) {
4608 u = new_label[u];
4609 v = new_label[v];
4610 if (u > v)
4611 std::swap(u, v);
4612 }
4613
4614 // Permutes vertex weights to match the new labels.
4615 if (vertex_weights_.has_value()) {
4616 std::vector<VWeight> new_vw(n());
4617 for (int i = 0; i < n(); ++i)
4618 new_vw[new_label[i]] = (*vertex_weights_)[i];
4619 vertex_weights_ = std::move(new_vw);
4620 }
4621
4622 // Rebuilds the dsu so future `add_edge` calls see the new labels.
4623 dsu_ = detail::dsu(n());
4624 for (auto [u, v] : edges_)
4625 dsu_.unite(u, v);
4626
4627 // Shuffles edge order, keeping edge weights aligned.
4628
4629 std::vector<int> perm(edges_.size());
4630 std::iota(perm.begin(), perm.end(), 0);
4631 tgen::shuffle(perm.begin(), perm.end());
4632
4633 std::vector<std::pair<int, int>> new_edges;
4634 std::optional<std::vector<EWeight>> new_ew;
4635 if (edge_weights_.has_value())
4636 new_ew = std::vector<EWeight>();
4637 for (int i : perm) {
4638 new_edges.push_back(edges_[i]);
4639 if (new_ew.has_value())
4640 new_ew->push_back((*edge_weights_)[i]);
4641 }
4642 edges_ = new_edges;
4643 if (new_ew.has_value())
4644 edge_weights_ = new_ew;
4645
4646 return *this;
4647 }
4648
4649 // Shuffles the tree's vertices and edge order.
4650 // O(n).
4651 value &shuffle() { return shuffle_except({}); }
4652
4653 // Adds edge (u, v).
4654 // O(log n) amortized.
4655 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {
4656 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),
4657 "wtree: value: vertex ids must be valid");
4658
4659 if (u > v)
4660 std::swap(u, v);
4661
4662 if (adj_[u].count(v))
4663 return *this;
4664
4665 adj_[u].insert(v);
4666 adj_[v].insert(u);
4667 edges_.emplace_back(u, v);
4668 tgen_ensure(dsu_.unite(u, v),
4669 "wtree: value: added edge must not create a cycle");
4670
4671 if (w.has_value()) {
4672 tgen_ensure(edge_weights().has_value(),
4673 "wtree: value: cannot add weighted edge to "
4674 "edge-unweighted tree");
4675
4676 edge_weights_->push_back(*w);
4677 } else
4678 tgen_ensure(!edge_weights().has_value(),
4679 "wtree: value: cannot add unweighted edge to "
4680 "edge-weighted tree");
4681
4682 return *this;
4683 }
4684
4685 // Links tree with another `rhs`, adding the edge between u (in left
4686 // tree) and v (in right tree). Ids for added vertices are updated
4687 // accordingly.
4688 // O(rhs.n + rhs.m * log n) amortized.
4689 value &link(const value &rhs, int new_u, int new_v,
4690 std::optional<EWeight> new_w = std::nullopt) {
4691 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and
4692 new_v < rhs.n(),
4693 "wtree: value: vertex ids must be valid");
4694
4695 // Edges from right-hand side.
4696 int shift = n();
4697 add_vertices(rhs.n(), rhs.vertex_weights());
4698 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {
4699 auto [u, v] = rhs.edges()[i];
4700 add_edge(shift + u, shift + v,
4701 rhs.edge_weights().has_value()
4702 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4703 : std::nullopt);
4704 }
4705
4706 // New edge.
4707 add_edge(new_u, shift + new_v, new_w);
4708
4709 return *this;
4710 }
4711
4712 // Glues the tree with another `rhs` such that index_pairs[i].first is
4713 // considered to be the same as index_pairs[i].second. Ids for added
4714 // vertices are updated accordingly.
4715 // O(rhs.n + rhs.m * log n) amortized.
4716 value &glue(const value &rhs,
4717 std::set<std::pair<int, int>> index_pairs) {
4718 // Checks validity of indices.
4719 std::set<int> idx_left, idx_right;
4720 std::vector<int> right_id_to_left(rhs.n(), -1);
4721 for (auto [l, r] : index_pairs) {
4723 0 <= l and l < n() and 0 <= r and r < rhs.n(),
4724 "wtree: value: vertex indices to glue must be valid");
4725 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,
4726 "wtree: value: must not have repeated indices "
4727 "on the same side to glue");
4728
4729 idx_left.insert(l);
4730 idx_right.insert(r);
4731 right_id_to_left[r] = l;
4732 }
4733
4734 // Computes new ids of right vertices.
4735 std::vector<int> new_right_id(rhs.n(), -1);
4736 int intersection_lt = 0;
4737 std::optional<std::vector<VWeight>> rhs_vertex_weights;
4738 for (int i = 0; i < rhs.n(); ++i) {
4739 if (right_id_to_left[i] != -1) {
4740 // Is in intersection.
4741 ++intersection_lt;
4742 new_right_id[i] = right_id_to_left[i];
4743 } else {
4744 // New id.
4745 new_right_id[i] = n() + i - intersection_lt;
4746 if (rhs.vertex_weights().has_value()) {
4747 if (!rhs_vertex_weights.has_value())
4748 rhs_vertex_weights = std::vector<VWeight>();
4749 rhs_vertex_weights->push_back(
4750 (*rhs.vertex_weights())[i]);
4751 }
4752 }
4753 }
4754
4755 // Adds new vertices and edges.
4756 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
4757 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {
4758 auto [u, v] = rhs.edges()[i];
4759 add_edge(new_right_id[u], new_right_id[v],
4760 rhs.edge_weights().has_value()
4761 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4762 : std::nullopt);
4763 }
4764
4765 return *this;
4766 }
4767 value &glue(const value &rhs,
4768 std::initializer_list<std::pair<int, int>> il) {
4769 return glue(rhs, std::set<std::pair<int, int>>(il));
4770 }
4771
4772 // Glues the tree with another `rhs` at `indices`. That is, idx in
4773 // `indices` are considered to be the same vertex. Ids for added
4774 // vertices are updated accordingly.
4775 // O(rhs.n).
4776 value &glue(const value &rhs, std::set<int> indices) {
4777 std::set<std::pair<int, int>> index_pairs;
4778 for (auto i : indices)
4779 index_pairs.emplace(i, i);
4780 return glue(rhs, index_pairs);
4781 }
4782 value &glue(const value &rhs, const std::initializer_list<int> &il) {
4783 return glue(rhs, std::set<int>(il));
4784 }
4785
4786 // Prints to std::ostream.
4787 // O(n).
4788 friend std::ostream &operator<<(std::ostream &out, const value &val) {
4789 if (val.print_n_)
4790 out << val.n() << '\n';
4791
4792 // Prints vertex weights.
4793 if (val.vertex_weights()) {
4794 for (int i = 0; i < val.n(); ++i) {
4795 if (i > 0)
4796 out << " ";
4797 out << (*val.vertex_weights())[i];
4798 }
4799 out << '\n';
4800 }
4801
4802 tgen_ensure(static_cast<int>(val.edges().size()) == val.n() - 1,
4803 "wtree: value: invalid tree to print (number of edges "
4804 "must be `n` - 1)");
4805
4806 // Prints in parent style.
4807 if (val.print_parents_.has_value()) {
4808 tgen_ensure(!val.edge_weights().has_value(),
4809 "wtree: value: cannot print parent style if edges "
4810 "are weighted");
4811
4812 int root = *val.print_parents_;
4813 bool skip_parent_0 = root == -1;
4814 if (root == -1)
4815 root = 0;
4816 if (root == val.n())
4817 root = next(0, val.n() - 1);
4818
4819 std::vector<int> parent(val.n(), -1);
4820
4821 std::queue<int> q;
4822 std::vector<int> vis(val.n(), false);
4823 q.push(root);
4824 vis[root] = true;
4825
4826 while (q.size()) {
4827 int u = q.front();
4828 q.pop();
4829 for (int v : val.adj()[u])
4830 if (!vis[v]) {
4831 vis[v] = true;
4832 q.push(v);
4833 parent[v] = u;
4834 }
4835 }
4836
4837 if (skip_parent_0) {
4838 for (int i = 1; i < val.n(); ++i) {
4840 parent[i] < i,
4841 "wtree: value: parent of i must be less than i for "
4842 "printing in parent style if root is -1");
4843
4844 if (i > 1)
4845 out << " ";
4846 out << parent[i] + val.print_1_based_;
4847 }
4848 } else {
4849 for (int i = 0; i < val.n(); ++i) {
4850 if (i > 0)
4851 out << " ";
4852 out << (parent[i] == -1 ? -1 : parent[i]) +
4853 val.print_1_based_;
4854 }
4855 }
4856
4857 out << '\n';
4858 return out;
4859 }
4860
4861 // Prints edges.
4862 for (int i = 0; i < static_cast<int>(val.edges().size()); ++i) {
4863 auto [u, v] = val.edges()[i];
4864 out << (u + val.print_1_based_) << " "
4865 << (v + val.print_1_based_);
4866
4867 // Edge weight.
4868 if (val.edge_weights().has_value())
4869 out << " " << (*val.edge_weights())[i];
4870
4871 out << '\n';
4872 }
4873
4874 return out;
4875 }
4876
4877 // Gets a std::pair<n, adj> representing the value (0-based).
4878 // Unaffected by print_1_based().
4879 std::pair<int, std::vector<std::set<int>>> to_std() const {
4880 return std_type(n_, adj_);
4881 }
4882
4883 // Gets a 1-based (n, adj): labels +1, adj size n+1, index 0 unused.
4884 // Unaffected by print_1_based().
4885 std::pair<int, std::vector<std::set<int>>> to_std_1_based() const {
4886 std::vector<std::set<int>> adj(n_ + 1);
4887 for (int u = 0; u < n_; ++u)
4888 for (int v : adj_[u])
4889 adj[u + 1].insert(v + 1);
4890 return std_type(n_, adj);
4891 }
4892
4893 private:
4894 // Adds `k` vertices to the tree (labeled n, n+1, ...n+k-1). Updates
4895 // `n` accordingly. This makes the tree invalid (not a tree anymore).
4896 // O(k) amortized.
4897 value &add_vertices(int k, std::optional<std::vector<VWeight>>
4898 new_vertex_weights = std::nullopt) {
4899 n_ += k;
4900 adj_.resize(n());
4901 if (new_vertex_weights.has_value()) {
4902 tgen_ensure(vertex_weights().has_value(),
4903 "wtree: value: cannot add weighted vertices to "
4904 "vertex-unweighted tree");
4906 static_cast<int>(new_vertex_weights->size()) == k,
4907 "wtree: value: number of vertex weights must be equal "
4908 "to number of added vertices");
4909
4910 vertex_weights_->insert(vertex_weights_->end(),
4911 new_vertex_weights->begin(),
4912 new_vertex_weights->end());
4913 } else
4914 tgen_ensure(!vertex_weights().has_value(),
4915 "wtree: value: cannot add unweighted vertices to "
4916 "vertex-weighted tree");
4917
4918 dsu_.add_elements(k);
4919
4920 return *this;
4921 }
4922 };
4923
4924 // Generates tree value.
4925 // O(n).
4926 value gen() const {
4927 // Constructs adjacency list.
4928 std::vector<std::vector<int>> adj(n_);
4929 for (auto [u, v] : edges_) {
4930 adj[u].push_back(v);
4931 adj[v].push_back(u);
4932 }
4933
4934 std::vector<int> comp_size;
4935 std::vector<std::vector<int>> component_ids;
4936 std::vector<bool> vis(n_, false);
4937 std::queue<int> q;
4938
4939 for (int i = 0; i < n_; ++i) {
4940 if (vis[i])
4941 continue;
4942
4943 vis[i] = true;
4944 q.push(i);
4945 comp_size.push_back(0);
4946 component_ids.emplace_back();
4947 while (q.size()) {
4948 int u = q.front();
4949 q.pop();
4950 ++comp_size.back();
4951 component_ids.back().push_back(u);
4952 for (int v : adj[u]) {
4953 if (!vis[v]) {
4954 vis[v] = true;
4955 q.push(v);
4956 }
4957 }
4958 }
4959 }
4960
4961 // Creates edges connecting the connected components by treating them as
4962 // vertices.
4963 std::vector<std::pair<int, int>> new_edges(edges_.begin(),
4964 edges_.end());
4965 if (comp_size.size() > 1) {
4966 std::vector<int> prufer_values =
4967 many_by_distribution(comp_size.size() - 2, comp_size);
4968 for (auto [u, v] : detail::edges_from_prufer(prufer_values))
4969 new_edges.emplace_back(pick(component_ids[u]),
4970 pick(component_ids[v]));
4971 }
4972
4973 return value(n_, new_edges);
4974 }
4975
4976 // Generates a (not uniformly) random skewed tree.
4977 // Vertex 0 is the root. For each i in 1 .. n-1, parent(i) is
4978 // wnext(i, elongation), i.e. a value in [0, i) with skew controlled by
4979 // elongation (see wnext).
4980 // If elongation is small enough, generates a star (center 0).
4981 // If elongation is large enough, generates a path (endpoints 0 and n-1).
4982 // O(n).
4983 static value gen_skewed(int n, int elongation) {
4984 std::vector<std::pair<int, int>> edges;
4985 for (int i = 1; i < n; ++i)
4986 edges.emplace_back(i, wnext<int>(i, elongation));
4987 return value(n, edges);
4988 }
4989
4990 // Kruskal-like random tree: random vertex pairs until connected.
4991 // Not uniformly random.
4992 // O(n log(n) alpha(n)) expected.
4993 static value gen_kruskal(int n) {
4994 tgen_ensure(n > 0, "wtree: gen_kruskal: n must be positive");
4995 if (n == 1)
4996 return value(1, {});
4997
4998 detail::dsu components(n);
4999 std::vector<std::pair<int, int>> edges;
5000 edges.reserve(n - 1);
5001 while (edges.size() < size_t(n - 1)) {
5002 int u = next(0, n - 1);
5003 int v = next(0, n - 1);
5004 if (u == v)
5005 continue;
5006 if (components.unite(u, v))
5007 edges.emplace_back(u, v);
5008 }
5009 return value(n, edges);
5010 }
5011};
5012
5013/*
5014 * Other types of weighted-ness.
5015 */
5016
5017// Vertex weighted tree.
5018template <typename VWeight> using vtree = wtree<VWeight, int>;
5019
5020// Edge weighted tree.
5021template <typename EWeight> using etree = wtree<int, EWeight>;
5022
5023// Unweighted tree.
5024using tree = wtree<int, int>;
5025
5026/*************
5027 * *
5028 * GRAPH *
5029 * *
5030 *************/
5031
5032namespace detail {
5033
5034// Canonical undirected edge key for duplicate detection; stores (min(u, v),
5035// max(u, v)). O(1).
5036inline uint64_t undirected_edge_key(int u, int v) {
5037 if (u > v)
5038 std::swap(u, v);
5039 return (static_cast<uint64_t>(u) << 32) |
5040 static_cast<uint64_t>(static_cast<uint32_t>(v));
5041}
5042
5043// Directed edge key for duplicate detection; stores (u, v).
5044// O(1).
5045inline uint64_t directed_edge_key(int u, int v) {
5046 return (static_cast<uint64_t>(u) << 32) |
5047 static_cast<uint64_t>(static_cast<uint32_t>(v));
5048}
5049
5050// Maximum number of edges in a simple graph on n vertices.
5051// O(1).
5052inline long long max_graph_edges(int n, bool directed, bool self_loops) {
5053 if (n <= 0)
5054 return 0;
5055 if (directed)
5056 return self_loops ? static_cast<long long>(n) * n
5057 : static_cast<long long>(n) * (n - 1);
5058 return self_loops ? static_cast<long long>(n) * (n + 1) / 2
5059 : static_cast<long long>(n) * (n - 1) / 2;
5060}
5061
5062// Uniform random edge for rejection sampling.
5063// O(1) expected.
5064inline std::pair<int, int> get_random_graph_edge(int n, bool directed,
5065 bool self_loops) {
5066 if (directed) {
5067 if (self_loops)
5068 return {next<int>(0, n - 1), next<int>(0, n - 1)};
5069 int u = next<int>(0, n - 1);
5070 int v = next<int>(0, n - 1);
5071 while (u == v)
5072 v = next<int>(0, n - 1);
5073 return {u, v};
5074 }
5075 if (self_loops) {
5076 int u = next<int>(0, n - 1);
5077 int v = next<int>(0, n - 1);
5078 if (u > v)
5079 std::swap(u, v);
5080 return {u, v};
5081 }
5082 int u = next<int>(0, n - 1);
5083 int v = next<int>(0, n - 1);
5084 while (u == v)
5085 v = next<int>(0, n - 1);
5086 if (u > v)
5087 std::swap(u, v);
5088 return {u, v};
5089}
5090
5091// Decodes a linear edge index to (u, v) for an undirected simple graph,
5092// with u < v.
5093// O(log n).
5094inline std::pair<int, int> decode_undirected_simple_edge(int n, long long idx) {
5095 auto base = [&](int u) -> long long {
5096 return static_cast<long long>(u) * (n - 1) -
5097 static_cast<long long>(u) * (u - 1) / 2;
5098 };
5099 int lo = 0, hi = n - 2;
5100 while (lo < hi) {
5101 int mid = (lo + hi + 1) / 2;
5102 if (base(mid) <= idx)
5103 lo = mid;
5104 else
5105 hi = mid - 1;
5106 }
5107 return {lo, lo + 1 + int(idx - base(lo))};
5108}
5109
5110// Decodes a linear edge index to (u, v) for an undirected graph with loops,
5111// with u <= v.
5112// O(log n).
5113inline std::pair<int, int> decode_undirected_loops_edge(int n, long long idx) {
5114 auto base = [&](int u) -> long long {
5115 return static_cast<long long>(u) * n -
5116 static_cast<long long>(u) * (u - 1) / 2;
5117 };
5118 int lo = 0, hi = n - 1;
5119 while (lo < hi) {
5120 int mid = (lo + hi + 1) / 2;
5121 if (base(mid) <= idx)
5122 lo = mid;
5123 else
5124 hi = mid - 1;
5125 }
5126 return {lo, lo + int(idx - base(lo))};
5127}
5128
5129// Decodes a linear edge index to (u, v) for a directed simple graph (no loops).
5130// O(1).
5131inline std::pair<int, int> decode_directed_simple_edge(int n, long long idx) {
5132 int u = idx / (n - 1);
5133 int rem = idx % (n - 1);
5134 return {u, rem + (rem >= u)};
5135}
5136
5137// Decodes a linear edge index according to graph mode.
5138// O(log n) for undirected, O(1) for directed.
5139inline std::pair<int, int>
5140decode_graph_edge_index(int n, long long idx, bool directed, bool self_loops) {
5141 if (directed) {
5142 if (self_loops)
5143 return {int(idx / n), int(idx % n)};
5144 return decode_directed_simple_edge(n, idx);
5145 }
5146 if (self_loops)
5147 return decode_undirected_loops_edge(n, idx);
5148 return decode_undirected_simple_edge(n, idx);
5149}
5150
5151} // namespace detail
5152
5153/*
5154 * Graph generator.
5155 *
5156 * Graphs of `n` vertices labeled from 0 to n-1 and `m` edges.
5157 * These are labeled graphs, that is, isomorphism is not taken into
5158 * account. VWeight is the type of vertex weights, and EWeight is the type of
5159 * edge weights. Generator does not generate weights. The weights are to be set
5160 * in the wgraph::value.
5161 */
5162
5163template <typename VWeight, typename EWeight>
5164struct wgraph : gen_base<wgraph<VWeight, EWeight>> {
5165 int n_, m_; // Number of vertices and edges.
5166 std::set<std::pair<int, int>> edges_; // Edges that were set.
5167 bool is_directed_; // If graph is directed.
5168 bool has_self_loops_; // If self-loops are allowed.
5169
5170 // Creates graph generator with `n` vertices and `m` edges.
5171 // Additionally, you can set if the graph is directed and if self loops are
5172 // allowed.
5173 // O(1).
5174 wgraph(int n, int m, bool is_directed = false, bool has_self_loops = false)
5175 : n_(n), m_(m), is_directed_(is_directed),
5176 has_self_loops_(has_self_loops) {
5177 tgen_ensure(n > 0, "wgraph: number of vertices must be positive");
5178 }
5179
5180 // Adds edge between u and v (this edge must be generated).
5181 // O(log m).
5182 wgraph &add_edge(int u, int v) {
5183 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,
5184 "wgraph: vertices must be indexed in [0, n)");
5185
5186 if (!is_directed_ and u > v)
5187 std::swap(u, v);
5188 edges_.emplace(u, v);
5189 tgen_ensure(static_cast<int>(edges_.size()) <= m_,
5190 "wgraph: too many edges were added");
5191 return *this;
5192 }
5193
5194 // Graph value.
5195 //
5196 // Edges are stored in both directions (if undirected) in adjacency list,
5197 // but only u < v in edge list.
5198 // Optimized for performance (lazy adjacency list; edge-list constructor
5199 // stores edges only).
5201 using std_type = std::tuple<int, int, std::vector<std::set<int>>>;
5202
5203 int n_; // Number of vertices.
5204 std::vector<std::set<int>> adj_; // Adjacency list.
5205 std::vector<std::pair<int, int>> edges_; // Edge list.
5206 bool is_directed_; // If graph is directed.
5207 bool print_1_based_; // If should print vertex ids 1-based (print only).
5208 bool print_nm_; // If should print n and m.
5209 mutable bool adj_built_{
5210 false}; // Lazy cache: true once adj_ is built from edges_; mutable
5211 // so const adj() can populate it.
5212 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.
5213 std::optional<std::vector<EWeight>>
5214 edge_weights_; // Edge weights (in same order as edges_ ).
5215
5216 // Creates value from adjacency list. The edges
5217 // are considered to be directed.
5218 // O(n + m).
5219 value(const std::vector<std::set<int>> &adj, bool is_directed = false)
5220 : n_(static_cast<int>(adj.size())), adj_(adj),
5221 is_directed_(is_directed), print_1_based_(false),
5222 print_nm_(false), adj_built_(true) {
5223 for (int u = 0; u < n_; ++u)
5224 for (auto v : adj[u]) {
5226 0 <= v and v < n_,
5227 "wgraph: value: vertices must be indexed in [0, n)");
5228 // Undirected adjacency is symmetric: count each edge once
5229 // (canonical u <= v). Directed: every out-edge appears
5230 // once.
5231 if (is_directed_ or u <= v)
5232 edges_.emplace_back(u, v);
5233 }
5234 }
5235
5236 // Creates value from `n`, `m`, and edge list. The edges are
5237 // considered to be directed.
5238 // Optimized for performance (lazy adjacency list; unordered_set dedup).
5239 // O(m log m).
5240 value(int n, const std::vector<std::pair<int, int>> &edges = {},
5241 bool is_directed = false)
5242 : n_(n), edges_(), is_directed_(is_directed), print_1_based_(false),
5243 print_nm_(false), adj_built_(false) {
5244 edges_.reserve(edges.size());
5245 std::unordered_set<uint64_t> seen;
5246 seen.reserve(edges.size() * 2 + 1);
5247 for (auto [u, v] : edges) {
5249 0 <= std::min(u, v) and std::max(u, v) < n,
5250 "wgraph: value: vertices must be indexed in [0, n)");
5251 if (!is_directed_ and u > v)
5252 std::swap(u, v);
5253 uint64_t key = is_directed_ ? detail::directed_edge_key(u, v)
5254 : detail::undirected_edge_key(u, v);
5255 if (seen.insert(key).second)
5256 edges_.emplace_back(u, v);
5257 }
5258 }
5259 value(int n, const std::set<std::pair<int, int>> &edges,
5260 bool is_directed = false)
5261 : value(
5262 n,
5263 std::vector<std::pair<int, int>>(edges.begin(), edges.end()),
5264 is_directed) {}
5265 value(int n, const std::initializer_list<std::pair<int, int>> &edges,
5266 bool is_directed = false)
5267 : value(n, std::vector<std::pair<int, int>>(edges), is_directed) {}
5268
5269 // Creates graph from tree (undirected, same edges).
5270 // O(n).
5271 value(const typename wtree<VWeight, EWeight>::value &t)
5272 : value(t.n(), t.edges(), false) {
5273 if (t.vertex_weights().has_value()) {
5274 vertex_weights_ = *t.vertex_weights();
5275 }
5276 if (t.edge_weights().has_value()) {
5277 edge_weights_ = *t.edge_weights();
5278 }
5279 }
5280
5281 // Weight type conversion.
5282 // O(n + m).
5283 template <typename NewVWeight, typename NewEWeight>
5284 typename wgraph<NewVWeight, NewEWeight>::value
5285 convert_weight_types() const {
5286 tgen_ensure(!vertex_weights_.has_value() and
5287 !edge_weights_.has_value(),
5288 "wgraph: value: cannot convert weight type after "
5289 "assigning weights");
5290
5291 ensure_adj_built();
5292 typename wgraph<NewVWeight, NewEWeight>::value new_graph(
5293 adj_, is_directed_);
5294 new_graph.is_directed_ = is_directed_;
5295 new_graph.print_1_based_ = print_1_based_;
5296 new_graph.print_nm_ = print_nm_;
5297 return new_graph;
5298 }
5299
5300 // Fetches number of vertices.
5301 int n() const { return n_; }
5302
5303 // Fetches number of edges.
5304 int m() const { return edges_.size(); }
5305
5306 // Fetches if graph is directed;
5307 bool is_directed() const { return is_directed_; }
5308
5309 // Fetches a const ref. to adjacency list.
5310 const std::vector<std::set<int>> &adj() const {
5311 ensure_adj_built();
5312 return adj_;
5313 }
5314
5315 // Fetches a const ref. to edge set.
5316 const std::vector<std::pair<int, int>> &edges() const { return edges_; }
5317
5318 // Fetches vertex weights.
5320 return vertex_weights_;
5321 }
5322
5323 // Fetches edge weights.
5325 return edge_weights_;
5326 }
5327
5328 // Sets vertex weights.
5329 // O(n + m).
5330 template <typename NewVWeight = VWeight>
5331 typename wgraph<NewVWeight, EWeight>::value set_vertex_weights(
5332 const std::vector<NewVWeight> &vertex_weights) const {
5333 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),
5334 "wgraph: value: must give `n` vertex weights");
5335
5336 auto new_graph = convert_weight_types<NewVWeight, EWeight>();
5337 new_graph.vertex_weights_ = vertex_weights;
5338 return new_graph;
5339 }
5340
5341 // Sets edge weights.
5342 // O(n + m).
5343 template <typename NewEWeight = EWeight>
5344 typename wgraph<VWeight, NewEWeight>::value
5345 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {
5346 tgen_ensure(static_cast<int>(edge_weights.size()) == m(),
5347 "wgraph: value: must give `m` edge weights");
5348
5349 auto new_graph = convert_weight_types<VWeight, NewEWeight>();
5350 new_graph.edge_weights_ = edge_weights;
5351 return new_graph;
5352 }
5353
5354 // Enables edge-weighted mode before adding weighted edges
5355 // incrementally. The graph must have no edges yet. O(1).
5357 tgen_ensure(m() == 0,
5358 "wgraph: value: edge_weighted requires a graph with no "
5359 "edges");
5360 tgen_ensure(!edge_weights_.has_value(),
5361 "wgraph: value: graph is already edge-weighted");
5362
5363 edge_weights_ = std::vector<EWeight>();
5364 return *this;
5365 }
5366
5367 // Sets that should print vertex ids 1-based. Does not change stored
5368 // ids; use to_std_1_based() for a 1-based export.
5369 // O(1).
5371 print_1_based_ = true;
5372 return *this;
5373 }
5374
5375 // Prints `n m` on a new line before printing the edges.
5376 // O(1).
5378 print_nm_ = true;
5379 return *this;
5380 }
5381
5382 // Shuffles the graph's vertex labels (except those in `indices`,
5383 // which keep their current label) and edge order. The change is
5384 // applied eagerly to the underlying adjacency list, edge list,
5385 // vertex weights and edge weights.
5386 // O(n + m).
5387 value &shuffle_except(std::set<int> indices) {
5388 ensure_adj_built();
5389 // Builds the relabeling: for each vertex `i`, `new_label[i]` is
5390 // its new id. Vertices in `indices` keep their label; the others
5391 // are permuted among themselves.
5392 std::vector<int> new_label(n());
5393 std::vector<int> shuffled;
5394 for (int i = 0; i < n(); ++i) {
5395 if (indices.count(i))
5396 new_label[i] = i;
5397 else
5398 shuffled.push_back(i);
5399 }
5400 std::vector<int> targets = shuffled;
5401 tgen::shuffle(targets.begin(), targets.end());
5402 for (size_t k = 0; k < shuffled.size(); ++k)
5403 new_label[shuffled[k]] = targets[k];
5404
5405 // Rewrites adjacency list with new labels.
5406 std::vector<std::set<int>> new_adj(n());
5407 for (int u = 0; u < n(); ++u)
5408 for (int v : adj_[u])
5409 new_adj[new_label[u]].insert(new_label[v]);
5410 adj_ = new_adj;
5411
5412 // Rewrites edges with new labels (canonical undirected order).
5413 for (auto &[u, v] : edges_) {
5414 u = new_label[u];
5415 v = new_label[v];
5416 if (!is_directed_ and u > v)
5417 std::swap(u, v);
5418 }
5419
5420 // Permutes vertex weights to match the new labels.
5421 if (vertex_weights_.has_value()) {
5422 std::vector<VWeight> new_vw(n());
5423 for (int i = 0; i < n(); ++i)
5424 new_vw[new_label[i]] = (*vertex_weights_)[i];
5425 vertex_weights_ = new_vw;
5426 }
5427
5428 // Shuffles edge order, keeping edge weights aligned.
5429
5430 std::vector<int> perm(edges_.size());
5431 std::iota(perm.begin(), perm.end(), 0);
5432 tgen::shuffle(perm.begin(), perm.end());
5433
5434 std::vector<std::pair<int, int>> new_edges;
5435 std::optional<std::vector<EWeight>> new_ew;
5436 if (edge_weights_.has_value())
5437 new_ew = std::vector<EWeight>();
5438 for (int i : perm) {
5439 new_edges.push_back(edges_[i]);
5440 if (new_ew.has_value())
5441 new_ew->push_back((*edge_weights_)[i]);
5442 }
5443
5444 edges_ = new_edges;
5445 if (new_ew.has_value())
5446 edge_weights_ = new_ew;
5447
5448 return *this;
5449 }
5450
5451 // Shuffles the graph's vertices and edge order.
5452 // O(n + m).
5453 value &shuffle() { return shuffle_except({}); }
5454
5455 // Adds `k` vertices to the graph (labeled n, n+1, ...n+k-1). Updates
5456 // `n` accordingly.
5457 // O(k) amortized.
5458 value &add_vertices(int k, std::optional<std::vector<VWeight>>
5459 new_vertex_weights = std::nullopt) {
5460 ensure_adj_built();
5461 n_ += k;
5462 adj_.resize(n());
5463 if (new_vertex_weights.has_value()) {
5464 tgen_ensure(vertex_weights().has_value(),
5465 "wgraph: value: cannot add weighted vertices to "
5466 "vertex-unweighted graph");
5468 static_cast<int>(new_vertex_weights->size()) == k,
5469 "wgraph: value: number of vertex weights must be equal "
5470 "to number of added vertices");
5471
5472 vertex_weights_->insert(vertex_weights_->end(),
5473 new_vertex_weights->begin(),
5474 new_vertex_weights->end());
5475 } else
5476 tgen_ensure(!vertex_weights().has_value(),
5477 "wgraph: value: cannot add unweighted vertices to "
5478 "vertex-weighted graph");
5479
5480 return *this;
5481 }
5482
5483 // Adds edge (u, v).
5484 // O(log n) amortized.
5485 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {
5486 ensure_adj_built();
5487 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),
5488 "wgraph: value: vertex ids must be valid");
5489
5490 if (!is_directed() and u > v)
5491 std::swap(u, v);
5492
5493 if (adj_[u].count(v))
5494 return *this;
5495
5496 adj_[u].insert(v);
5497 if (!is_directed())
5498 adj_[v].insert(u);
5499 edges_.emplace_back(u, v);
5500
5501 if (w.has_value()) {
5502 tgen_ensure(edge_weights().has_value(),
5503 "wgraph: value: cannot add weighted edge to "
5504 "edge-unweighted graph");
5505
5506 edge_weights_->push_back(*w);
5507 } else
5508 tgen_ensure(!edge_weights().has_value(),
5509 "wgraph: value: cannot add unweighted edge to "
5510 "edge-weighted graph");
5511
5512 return *this;
5513 }
5514
5515 // Links graph with another `rhs`, adding the edge between u (in left
5516 // graph) and v (in right graph). Ids for added vertices are updated
5517 // accordingly.
5518 // O(rhs.n + rhs.m * log n) amortized.
5519 value &link(const value &rhs, int new_u, int new_v,
5520 std::optional<EWeight> new_w = std::nullopt) {
5521 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and
5522 new_v < rhs.n(),
5523 "wgraph: value: vertex ids must be valid");
5524
5525 // Edges from right-hand side.
5526 int shift = n();
5527 add_vertices(rhs.n(), rhs.vertex_weights());
5528 for (int i = 0; i < rhs.m(); ++i) {
5529 auto [u, v] = rhs.edges()[i];
5530 add_edge(shift + u, shift + v,
5531 rhs.edge_weights().has_value()
5532 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5533 : std::nullopt);
5534 }
5535
5536 // New edge.
5537 add_edge(new_u, shift + new_v, new_w);
5538
5539 return *this;
5540 }
5541
5542 // Glues the graph with another `rhs` such that index_pairs[i].first is
5543 // considered to be the same as index_pairs[i].second. Ids for added
5544 // vertices are updated accordingly.
5545 // O(rhs.n + rhs.m * log n) amortized.
5546 value &glue(const value &rhs,
5547 std::set<std::pair<int, int>> index_pairs) {
5550 "wgraph: value: graphs must have the same is_directed value");
5551
5552 // Checks validity of indices.
5553 std::set<int> idx_left, idx_right;
5554 std::vector<int> right_id_to_left(rhs.n(), -1);
5555 for (auto [l, r] : index_pairs) {
5557 0 <= l and l < n() and 0 <= r and r < rhs.n(),
5558 "wgraph: value: vertex indices to glue must be valid");
5559 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,
5560 "wgraph: value: must not have repeated indices "
5561 "on the same side to glue");
5562
5563 idx_left.insert(l);
5564 idx_right.insert(r);
5565 right_id_to_left[r] = l;
5566 }
5567
5568 // Computes new ids of right vertices.
5569 std::vector<int> new_right_id(rhs.n(), -1);
5570 int intersection_lt = 0;
5571 std::optional<std::vector<VWeight>> rhs_vertex_weights;
5572 for (int i = 0; i < rhs.n(); ++i) {
5573 if (right_id_to_left[i] != -1) {
5574 // Is in intersection.
5575 ++intersection_lt;
5576 new_right_id[i] = right_id_to_left[i];
5577 } else {
5578 // New id.
5579 new_right_id[i] = n() + i - intersection_lt;
5580 if (rhs.vertex_weights().has_value()) {
5581 if (!rhs_vertex_weights.has_value())
5582 rhs_vertex_weights = std::vector<VWeight>();
5583 rhs_vertex_weights->push_back(
5584 (*rhs.vertex_weights())[i]);
5585 }
5586 }
5587 }
5588
5589 // Adds new vertices and edges.
5590 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
5591 for (int i = 0; i < rhs.m(); ++i) {
5592 auto [u, v] = rhs.edges()[i];
5593 add_edge(new_right_id[u], new_right_id[v],
5594 rhs.edge_weights().has_value()
5595 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5596 : std::nullopt);
5597 }
5598
5599 return *this;
5600 }
5601 value &glue(const value &rhs,
5602 std::initializer_list<std::pair<int, int>> il) {
5603 return glue(rhs, std::set<std::pair<int, int>>(il));
5604 }
5605
5606 // Glues the graph with another `rhs` at `indices`. That is, idx in
5607 // `indices` are considered to be the same vertex. Ids for added
5608 // vertices are updated accordingly.
5609 // O(rhs.n + rhs.m * log n) amortized.
5610 value &glue(const value &rhs, std::set<int> indices) {
5611 std::set<std::pair<int, int>> index_pairs;
5612 for (auto i : indices)
5613 index_pairs.emplace(i, i);
5614 return glue(rhs, index_pairs);
5615 }
5616 value &glue(const value &rhs, const std::initializer_list<int> &il) {
5617 return glue(rhs, std::set<int>(il));
5618 }
5619
5620 // Disjoint union.
5621 // Shifts ids from `rhs` graph by n().
5622 // O(rhs.n + rhs.m * log n) amortized.
5624 return glue(rhs, std::set<int>());
5625 }
5626
5627 // Computes uniformly random subgraph of graph with num_edges edges.
5628 // O(n + m).
5629 value &random_subgraph(int num_edges) {
5631 num_edges <= m(),
5632 "wgraph: value: can choose at most `m` edges from graph");
5633
5634 std::vector<std::pair<int, int>> new_edges;
5635 std::optional<std::vector<EWeight>> new_edge_weights;
5636
5637 int left = m();
5638 for (int i = 0; i < m(); ++i) {
5639 if (next(1, left--) <= num_edges) {
5640 new_edges.push_back(edges()[i]);
5641 if (edge_weights_.has_value()) {
5642 if (!new_edge_weights.has_value())
5643 new_edge_weights = std::vector<EWeight>();
5644 new_edge_weights->push_back((*edge_weights())[i]);
5645 }
5646 --num_edges;
5647 }
5648 }
5649
5650 edges_ = new_edges;
5651 edge_weights_ = new_edge_weights;
5652 rebuild_adj_from_edge_list();
5653 return *this;
5654 }
5655
5656 // Computes a random (not uniform) subgraph with `num_edges` edges that
5657 // keeps every connected component connected (does not increase the
5658 // number of connected components).
5659 // 1. Picks a spanning forest via randomized Prim.
5660 // 2. Adds additional edges uniformly at random.
5661 // O(n + m).
5663 tgen_ensure(!is_directed_,
5664 "wgraph: value: random_connected_subgraph is only for "
5665 "undirected graphs");
5667 num_edges <= m(),
5668 "wgraph: value: can choose at most `m` edges from graph");
5669
5670 // Builds an incidence list: for each vertex, the (neighbor, edge
5671 // index) pairs.
5672 std::vector<std::vector<std::pair<int, int>>> incident(n());
5673 for (int i = 0; i < m(); ++i) {
5674 auto [u, v] = edges_[i];
5675 incident[u].emplace_back(v, i);
5676 incident[v].emplace_back(u, i);
5677 }
5678
5679 // Randomized Prim.
5680 std::vector<bool> vis(n(), false);
5681 std::vector<int> queue;
5682 std::vector<bool> in_tree(m(), false);
5683 int forest_edges = 0;
5684
5685 for (int start = 0; start < n(); ++start) {
5686 if (vis[start])
5687 continue;
5688 vis[start] = true;
5689 queue.push_back(start);
5690
5691 while (!queue.empty()) {
5692 int i = tgen::next<int>(0, queue.size() - 1);
5693 int u = queue[i];
5694 std::swap(queue[i], queue.back());
5695 queue.pop_back();
5696
5697 for (auto [v, edge_idx] : incident[u]) {
5698 if (!vis[v]) {
5699 vis[v] = true;
5700 queue.push_back(v);
5701 in_tree[edge_idx] = true;
5702 ++forest_edges;
5703 }
5704 }
5705 }
5706 }
5708 num_edges >= forest_edges,
5709 "wgraph: value: random_connected_subgraph needs at least "
5710 "`n - c` edges, where `c` is the number of connected "
5711 "components");
5712
5713 // Splits edge indices into forest edges and the rest.
5714 std::vector<int> tree_idx, rest_idx;
5715 for (int i = 0; i < m(); ++i) {
5716 if (in_tree[i])
5717 tree_idx.push_back(i);
5718 else
5719 rest_idx.push_back(i);
5720 }
5721
5722 tgen::shuffle(rest_idx.begin(), rest_idx.end());
5723
5724 std::vector<int> chosen_idx;
5725 chosen_idx.insert(chosen_idx.end(), tree_idx.begin(),
5726 tree_idx.end());
5727 chosen_idx.insert(chosen_idx.end(), rest_idx.begin(),
5728 rest_idx.begin() + num_edges - forest_edges);
5729
5730 detail::tgen_ensure_against_bug(
5731 static_cast<int>(chosen_idx.size()) == num_edges,
5732 "wgraph: value: chose a wrong number of edges");
5733
5734 std::vector<std::pair<int, int>> new_edges;
5735 std::optional<std::vector<EWeight>> new_edge_weights;
5736 if (edge_weights_.has_value())
5737 new_edge_weights = std::vector<EWeight>();
5738 for (int i : chosen_idx) {
5739 new_edges.push_back(edges_[i]);
5740 if (new_edge_weights.has_value())
5741 new_edge_weights->push_back((*edge_weights_)[i]);
5742 }
5743
5744 edges_ = new_edges;
5745 edge_weights_ = new_edge_weights;
5746 rebuild_adj_from_edge_list();
5747 return *this;
5748 }
5749
5750 // Complement. Self loops are maintained.
5751 // O(n^2).
5752 value operator!() const {
5753 tgen_ensure(!edge_weights_.has_value(),
5754 "wgraph: value: cannot compute complement of "
5755 "edge-weighted graph");
5756
5757 value complement = *this;
5758 complement.ensure_adj_built();
5759 std::vector<std::pair<int, int>> compl_edges;
5760 for (int i = 0; i < complement.n_; ++i) {
5761 std::set<int> complement_adj;
5762 for (int j = 0; j < complement.n_; ++j) {
5763 bool add_j = false;
5764 if (j == i and complement.adj_[i].count(j))
5765 add_j = true;
5766 if (j != i and !complement.adj_[i].count(j))
5767 add_j = true;
5768
5769 if (add_j) {
5770 complement_adj.insert(j);
5771 // If i > j and !is_directed(), we don't add the edge.
5772 if (i <= j or complement.is_directed_) {
5773 compl_edges.emplace_back(i, j);
5774 }
5775 }
5776 }
5777 std::swap(complement.adj_[i], complement_adj);
5778 }
5779 std::swap(complement.edges_, compl_edges);
5780
5781 return complement;
5782 }
5783
5784 // Concatenates two values.
5785 // O(N + M log N), N = n + rhs.n, M = m + rhs.m.
5786 value operator+(const value &rhs) const {
5788 "wgraph: value: graphs must have the same "
5789 "is_directed value");
5790
5791 tgen_ensure(vertex_weights().has_value() ==
5792 rhs.vertex_weights().has_value(),
5793 "wgraph: value: cannot concatenate vertex-weighted "
5794 "wgraph to unweighted");
5795 tgen_ensure(edge_weights().has_value() ==
5796 rhs.edge_weights().has_value(),
5797 "wgraph: value: cannot concatenate edge-weighted "
5798 "wgraph to unweighted");
5799
5800 value concat = *this;
5801 concat.glue(rhs, std::set<std::pair<int, int>>());
5802 concat.print_1_based_ = print_1_based_ | rhs.print_1_based_;
5803 concat.print_nm_ = print_nm_ | rhs.print_nm_;
5804
5805 return concat;
5806 }
5807
5808 // Prints to std::ostream.
5809 // O(n + m).
5810 friend std::ostream &operator<<(std::ostream &out, const value &val) {
5811 // Prints `n` and `m`.
5812 if (val.print_nm_)
5813 out << val.n() << " " << val.m() << '\n';
5814
5815 // Prints vertex weights.
5816 if (val.vertex_weights()) {
5817 for (int i = 0; i < val.n(); ++i) {
5818 if (i > 0)
5819 out << " ";
5820 out << (*val.vertex_weights())[i];
5821 }
5822 out << '\n';
5823 }
5824
5825 // Prints edges.
5826 for (int i = 0; i < val.m(); ++i) {
5827 auto [u, v] = val.edges()[i];
5828 out << (u + val.print_1_based_) << " "
5829 << (v + val.print_1_based_);
5830
5831 // Edge weight.
5832 if (val.edge_weights().has_value())
5833 out << " " << (*val.edge_weights())[i];
5834
5835 out << '\n';
5836 }
5837
5838 return out;
5839 }
5840
5841 // Gets a std::tuple<n, m, adj> representing the value (0-based).
5842 // Unaffected by print_1_based().
5843 std::tuple<int, int, std::vector<std::set<int>>> to_std() const {
5844 ensure_adj_built();
5845 return std_type(n_, m(), adj_);
5846 }
5847
5848 // Gets a 1-based (n, m, adj): labels +1, adj size n+1, index 0 unused.
5849 // Unaffected by print_1_based().
5850 std::tuple<int, int, std::vector<std::set<int>>>
5852 ensure_adj_built();
5853 std::vector<std::set<int>> adj(n_ + 1);
5854 for (int u = 0; u < n_; ++u)
5855 for (int v : adj_[u])
5856 adj[u + 1].insert(v + 1);
5857 return std_type(n_, m(), adj);
5858 }
5859
5860 private:
5861 // Rebuilds adjacency from edges_ after replacing the edge list (e.g.
5862 // subgraph operations).
5863 // O(m log n).
5864 void rebuild_adj_from_edge_list() {
5865 adj_.assign(n_, {});
5866 for (auto [u, v] : edges_) {
5867 adj_[u].insert(v);
5868 if (!is_directed_)
5869 adj_[v].insert(u);
5870 }
5871 adj_built_ = true;
5872 }
5873
5874 // Builds adj_ from edges_ on first use.
5875 // O(1) if already built; O(m log n) otherwise.
5876 void ensure_adj_built() const {
5877 if (adj_built_)
5878 return;
5879 const_cast<value *>(this)->rebuild_adj_from_edge_list();
5880 }
5881 };
5882
5883 // Adds all edges from `rhs` as preset edges.
5884 // O(rhs.m * log m).
5886 tgen_ensure(is_directed_ == rhs.is_directed(),
5887 "wgraph: graphs must have the same is_directed value");
5888
5889 for (auto [u, v] : rhs.edges())
5890 add_edge(u, v);
5891 return *this;
5892 }
5893
5894 // Generates graph value.
5895 // Optimized for performance: dense no-preset graphs use index sampling;
5896 // otherwise gen_remaining_edges.
5897 // O(n + m log^2 n) expected.
5898 value gen() const {
5899 detail::tgen_ensure_against_bug(static_cast<int>(edges_.size()) <= m_,
5900 "wgraph: too many edges were added");
5901
5902 // All edges already added.
5903 if (static_cast<int>(edges_.size()) == m_)
5904 return value(n_, edges_, is_directed_);
5905
5906 // Splits into two cases to optimize performance.
5907
5908 // No presets and m > max_edges / 2: sample m distinct edge indices.
5909 if (auto indexed = try_gen_by_edge_index())
5910 return *indexed;
5911
5912 // Otherwise: fill preset edges up to m_ with uniform random edges.
5913 return gen_remaining_edges(
5914 std::vector<std::pair<int, int>>(edges_.begin(), edges_.end()));
5915 }
5916
5917 // Gets a (not uniformly) random connected undirected graph.
5918 // 1. Preset edges induce a spanning forest on their components.
5919 // 2. Then, uniformly random edges between components are added.
5920 // 3. Remaining edges are added uniformly at random.
5921 // O(n + m log^2 n) expected.
5923 tgen_ensure(!is_directed_,
5924 "wgraph: get_connected is only for undirected graphs");
5925 tgen_ensure(m_ >= n_ - 1,
5926 "wgraph: connected graph needs at least n - 1 edges");
5927
5928 std::vector<std::pair<int, int>> edges;
5929 edges.reserve(m_);
5930
5931 if (edges_.empty()) {
5932 if (n_ > 1) {
5933 std::vector<int> prufer(n_ - 2);
5934 for (int i = 0; i < n_ - 2; ++i)
5935 prufer[i] = next<int>(0, n_ - 1);
5936 for (auto [u, v] : detail::edges_from_prufer(std::move(prufer)))
5937 edges.emplace_back(u, v);
5938 }
5939 } else {
5940 edges.assign(edges_.begin(), edges_.end());
5941
5942 std::vector<std::vector<int>> adj(n_);
5943 for (auto [u, v] : edges_) {
5944 adj[u].push_back(v);
5945 adj[v].push_back(u);
5946 }
5947
5948 std::vector<int> comp_size;
5949 std::vector<std::vector<int>> component_ids;
5950 std::vector<bool> vis(n_, false);
5951 std::queue<int> q;
5952
5953 for (int i = 0; i < n_; ++i) {
5954 if (vis[i])
5955 continue;
5956
5957 vis[i] = true;
5958 q.push(i);
5959 comp_size.push_back(0);
5960 component_ids.emplace_back();
5961 while (q.size()) {
5962 int u = q.front();
5963 q.pop();
5964 ++comp_size.back();
5965 component_ids.back().push_back(u);
5966 for (int v : adj[u]) {
5967 if (!vis[v]) {
5968 vis[v] = true;
5969 q.push(v);
5970 }
5971 }
5972 }
5973 }
5974
5975 if (component_ids.size() > 1) {
5976 std::vector<int> prufer_values =
5977 many_by_distribution(component_ids.size() - 2, comp_size);
5978 for (auto [u, v] :
5979 detail::edges_from_prufer(std::move(prufer_values)))
5980 edges.emplace_back(pick(component_ids[u]),
5981 pick(component_ids[v]));
5982 }
5983 }
5984
5985 return gen_remaining_edges(std::move(edges));
5986 }
5987
5988 // Gets a (not uniformly) random directed acyclic graph.
5989 // 1. Randomized Kahn (uniform choice among indegree-0 vertices) yields a
5990 // random topological order of the preset edges (which must be acyclic).
5991 // 2. Extra edges are sampled randomly using the order.
5992 // With no preset edges: sample a random graph then orient acyclically.
5993 // Optimized for performance (distinct upper-triangle edge-index sampling;
5994 // rejection instead of pair::distinct for preset edges).
5995 // O(n + m log^2 n) expected.
5997 tgen_ensure(is_directed_,
5998 "wgraph: get_acyclic is only for directed graphs");
5999
6000 if (edges_.empty()) {
6001 std::vector<int> order(n_);
6002 std::iota(order.begin(), order.end(), 0);
6003 for (int i = n_ - 1; i > 0; --i)
6004 std::swap(order[i], order[next(0, i)]);
6005
6006 const long long max_pairs =
6007 static_cast<long long>(n_) * (n_ - 1) / 2;
6008 tgen_ensure(m_ <= max_pairs,
6009 "wgraph: not enough edges to generate");
6010
6011 std::vector<std::pair<int, int>> edges;
6012 edges.reserve(m_);
6013 for (long long idx : distinct_range<long long>(0, max_pairs - 1)
6014 .gen_list(m_)
6015 .to_std()) {
6016 auto [i, j] = detail::decode_undirected_simple_edge(n_, idx);
6017 edges.emplace_back(order[i], order[j]);
6018 }
6019 return value(n_, edges, true);
6020 }
6021
6022 std::vector<std::vector<int>> adj(n_);
6023 std::vector<int> indeg(n_, 0);
6024 for (auto [u, v] : edges_) {
6025 adj[u].push_back(v);
6026 ++indeg[v];
6027 }
6028
6029 std::vector<int> available;
6030 for (int i = 0; i < n_; ++i)
6031 if (indeg[i] == 0)
6032 available.push_back(i);
6033
6034 // Random topological order using randomized Kahn's algorithm.
6035 std::vector<int> order;
6036 while (!available.empty()) {
6037 int idx = next(0, static_cast<int>(available.size()) - 1);
6038 int u = available[idx];
6039 std::swap(available[idx], available.back());
6040 available.pop_back();
6041
6042 order.push_back(u);
6043 for (int v : adj[u])
6044 if (--indeg[v] == 0)
6045 available.push_back(v);
6046 }
6047
6048 tgen_ensure(static_cast<int>(order.size()) == n_,
6049 "wgraph: preset edges contain a directed cycle");
6050
6051 value acyclic(n_, edges_, true);
6052
6053 // Generates final edges.
6054
6055 detail::tgen_ensure_against_bug(acyclic.m() <= m_,
6056 "wgraph: too many edges were added");
6057
6058 if (acyclic.m() < m_) {
6059 std::vector<int> order_pos(n_);
6060 for (int i = 0; i < n_; ++i)
6061 order_pos[order[i]] = i;
6062
6063 std::unordered_set<uint64_t> seen;
6064 seen.reserve(m_ * 2);
6065 for (auto [u, v] : acyclic.edges())
6066 seen.insert(
6067 detail::undirected_edge_key(order_pos[u], order_pos[v]));
6068
6069 const long long max_pairs =
6070 static_cast<long long>(n_) * (n_ - 1) / 2;
6071 while (acyclic.m() < m_) {
6072 std::pair<int, int> edge;
6073 if (!detail::try_generate_distinct(seen, [&] {
6074 long long idx = next<long long>(0, max_pairs - 1);
6075 edge = detail::decode_undirected_simple_edge(n_, idx);
6076 return detail::undirected_edge_key(edge.first,
6077 edge.second);
6078 }))
6079 throw detail::error("wgraph: not enough edges to generate");
6080 acyclic.add_edge(order[edge.first], order[edge.second]);
6081 }
6082 }
6083
6084 return acyclic;
6085 }
6086
6087 // Generates a (not uniformly) random skewed connected graph.
6088 // 1. Builds the same skewed labeled tree as wtree::gen_skewed(n,
6089 // elongation)(root 0, parent(i) = wnext(i, elongation) for i >= 1).
6090 // If is_directed, tree edges are oriented down the tree.
6091 // 2. Adds the remaining edges: pick an endpoint u uniformly;
6092 // pick k uniformly in [1, spread]; walk from u toward the root k
6093 // times along tree parents to get v; add edge (v, u).
6094 // If elongation is small, generates a graph with small diameter.
6095 // If elongation is large, generates a graph with large diameter, with
6096 // vertices 0 and n-1 being far apart.
6097 // O(n + m log n) if spread is O(1);
6098 // O(n log n + m log^2 n) expected otherwise.
6099 static value gen_skewed(int n, int m, int elongation, int spread,
6100 bool is_directed = false) {
6102 m >= n - 1,
6103 "wgraph: skewed graph needs at least n - 1 edges to be connected");
6104 tgen_ensure(spread >= 2,
6105 "wgraph: gen_skewed spread must be at least 2");
6106
6107 value skewed(n, {}, is_directed);
6108
6109 std::vector<int> parent(n), depth(n, 0);
6110 parent[0] = 0;
6111 for (int i = 1; i < n; ++i) {
6112 int p = wnext<int>(i, elongation);
6113 parent[i] = p;
6114 depth[i] = depth[p] + 1;
6115 skewed.add_edge(p, i);
6116 }
6117
6118 const int extra = m - (n - 1);
6119 if (extra == 0)
6120 return skewed;
6121
6122 // If spread is large, use binary lifting to find the ancestor.
6123 // Otherwise, enumerate O(n * spread) ancestor edges and sample
6124 // directly.
6125 constexpr int naive_ancestor_spread = 20;
6126
6127 if (spread <= naive_ancestor_spread) {
6128 std::vector<std::pair<int, int>> candidates;
6129 candidates.reserve(n * spread);
6130 for (int u = 0; u < n; ++u) {
6131 int max_k = std::min(spread, depth[u]);
6132 if (max_k < 2)
6133 continue;
6134 int v = parent[u];
6135 for (int k = 2; k <= max_k; ++k) {
6136 v = parent[v];
6137 candidates.emplace_back(v, u);
6138 }
6139 }
6140
6141 tgen_ensure(extra <= static_cast<int>(candidates.size()),
6142 "wgraph: not enough edges to generate");
6143
6144 for (auto [v, u] : choose(candidates, extra))
6145 skewed.add_edge(v, u);
6146 } else {
6147 // Binary lifting.
6148 int lg = 1;
6149 while ((1 << lg) <= n)
6150 ++lg;
6151
6152 std::vector<std::vector<int>> up(lg, std::vector<int>(n));
6153 for (int v = 0; v < n; ++v)
6154 up[0][v] = parent[v];
6155 for (int j = 1; j < lg; ++j)
6156 for (int v = 0; v < n; ++v)
6157 up[j][v] = up[j - 1][up[j - 1][v]];
6158
6159 // Creates uniform generator of edges (u, v) such that v is ancestor
6160 // of u. For that, every u has depth[u]-1 choices for v, so we
6161 // weight u by min(spread - 1, depth[u] - 1). After that we can
6162 // just pick the ancestor uniformly.
6163 std::vector<int> distribution = depth;
6164 for (int &d : distribution)
6165 d = std::max(0, std::min(spread - 1, d - 1));
6166 weighted_sampler vertex_choice(distribution);
6167 distinct extra_edges([&]() -> std::pair<int, int> {
6168 int u = vertex_choice.next();
6169 int k = next(2, spread);
6170 int v = u;
6171 for (int j = 0; j < lg; ++j)
6172 if (k >> j & 1)
6173 v = up[j][v];
6174 return {v, u};
6175 });
6176
6177 while (skewed.m() < m) {
6178 std::pair<int, int> edge;
6179 try {
6180 edge = extra_edges.gen();
6181 } catch (const std::runtime_error &e) {
6182 if (std::string(e.what()) ==
6183 "tgen: distinct: no more distinct values")
6184 throw detail::error(
6185 "wgraph: not enough edges to generate");
6186 throw e;
6187 }
6188
6189 skewed.add_edge(edge.first, edge.second);
6190 }
6191 }
6192
6193 return skewed;
6194 }
6195
6196 // Generates a random bipartite graph. The first side has vertices
6197 // 0 .. n1-1, the second n1 .. n1+n2-1.
6198 // Uniform when connected is false (distinct cross-edge indices).
6199 // When connected, bipartite Prüfer + rejection fill; not uniform over
6200 // connected bipartite graphs.
6201 // O(n1 + n2 + m log(n1 * n2)) expected.
6202 static value gen_bipartite(int n1, int n2, int m, bool connected = false) {
6203 tgen_ensure(m >= 0, "wgraph: number of edges must be nonnegative");
6204 long long num_edges = 1LL * n1 * n2;
6205 tgen_ensure(m <= num_edges,
6206 "wgraph: bipartite graph has at most n1 * n2 edges");
6207 if (connected)
6209 m >= n1 + n2 - 1,
6210 "wgraph: connected bipartite graph needs at least n1 + n2 - 1 "
6211 "edges");
6212
6213 if (!connected) {
6214 std::vector<std::pair<int, int>> edges;
6215 edges.reserve(m);
6216 for (long long idx : distinct_range<long long>(0, num_edges - 1)
6217 .gen_list(m)
6218 .to_std())
6219 edges.emplace_back(static_cast<int>(idx / n2),
6220 n1 + static_cast<int>(idx % n2));
6221 return value(n1 + n2, std::move(edges), false);
6222 }
6223
6224 std::unordered_set<uint64_t> used_edges;
6225 used_edges.reserve(m * 2);
6226 std::vector<std::pair<int, int>> edges;
6227 edges.reserve(m);
6228
6229 auto pack_edge = [](int u, int v) -> uint64_t {
6230 if (u > v)
6231 std::swap(u, v);
6232 return (static_cast<uint64_t>(u) << 32) | static_cast<uint32_t>(v);
6233 };
6234
6235 if (n1 > 0 and n2 > 0) {
6236 std::vector<int> prufer(n1 + n2 - 2);
6237 for (int i = 0; i < n2 - 1; ++i)
6238 prufer[i] = next(0, n1 - 1);
6239 for (int i = 0; i < n1 - 1; ++i)
6240 prufer[n2 - 1 + i] = next(n1, n1 + n2 - 1);
6241 shuffle(prufer.begin(), prufer.end());
6242 for (auto [u, v] : detail::edges_from_prufer(std::move(prufer))) {
6243 if (u > v)
6244 std::swap(u, v);
6245 if (used_edges.insert(pack_edge(u, v)).second)
6246 edges.emplace_back(u, v);
6247 }
6248 detail::tgen_ensure_against_bug(
6249 used_edges.size() == size_t(n1 + n2 - 1),
6250 "wgraph: invalid bipartite spanning tree size");
6251 }
6252
6253 while (edges.size() < size_t(m)) {
6254 int u = next(0, n1 - 1);
6255 int v = next(n1, n1 + n2 - 1);
6256 if (used_edges.insert(pack_edge(u, v)).second)
6257 edges.emplace_back(u, v);
6258 }
6259
6260 return value(n1 + n2, std::move(edges), false);
6261 }
6262
6263 // Random graph on n vertices; each admissible edge independently with
6264 // probability p. Equivalent to sampling m ~ Binomial(N, p) then a uniform
6265 // G(n, m), where N is the number of admissible edges for the given
6266 // directed / self-loop mode.
6267 // O(n^2 (1 + p log^2 n)) expected.
6268 static value gen_np(int n, double p, bool is_directed = false,
6269 bool has_self_loops = false) {
6270 tgen_ensure(n > 0, "wgraph: number of vertices must be positive");
6271 tgen_ensure(p >= 0 and p <= 1, "wgraph: probability must be in [0, 1]");
6272
6273 long long max_edges =
6274 detail::max_graph_edges(n, is_directed, has_self_loops);
6275
6276 long long m = 0;
6277 if (p == 1.0)
6278 m = max_edges;
6279 else if (p > 0.0)
6280 for (long long i = 0; i < max_edges; ++i)
6281 if (next<double>(0.0, 1.0) < p)
6282 ++m;
6283
6284 tgen_ensure(m <= std::numeric_limits<int>::max(),
6285 "wgraph: too many edges to generate");
6286 return wgraph(n, static_cast<int>(m), is_directed, has_self_loops)
6287 .gen();
6288 }
6289
6290 private:
6291 // If this generator has no preset edges and m is large relative to the
6292 // maximum edge count, sample by distinct edge index. Otherwise
6293 // std::nullopt.
6294 // Optimized for performance (index sampling instead of rejection).
6295 // O(m log n).
6296 std::optional<value> try_gen_by_edge_index() const {
6297 if (!edges_.empty())
6298 return std::nullopt;
6299
6300 long long max_edges =
6301 detail::max_graph_edges(n_, is_directed_, has_self_loops_);
6302 if (m_ > max_edges)
6303 throw detail::error("wgraph: not enough edges to generate");
6304 if (max_edges <= 0 or 2LL * m_ <= max_edges)
6305 return std::nullopt;
6306
6307 std::vector<std::pair<int, int>> edges;
6308 edges.reserve(m_);
6309 for (long long idx :
6310 distinct_range<long long>(0, max_edges - 1).gen_list(m_).to_std())
6311 edges.push_back(detail::decode_graph_edge_index(
6312 n_, idx, is_directed_, has_self_loops_));
6313
6314 return value(n_, edges, is_directed_);
6315 }
6316
6317 // Fills `edges` up to m_ with uniform random edges not already present.
6318 // Optimized for performance (uint64 edge keys + try_generate_distinct).
6319 // O(m log^2 n) expected.
6320 value gen_remaining_edges(std::vector<std::pair<int, int>> edges) const {
6321 detail::tgen_ensure_against_bug(static_cast<int>(edges.size()) <= m_,
6322 "wgraph: too many edges were added");
6323
6324 if (static_cast<int>(edges.size()) == m_)
6325 return value(n_, edges, is_directed_);
6326
6327 edges.reserve(m_);
6328
6329 std::unordered_set<uint64_t> seen;
6330 seen.reserve(m_ * 2);
6331 for (auto [u, v] : edges) {
6332 if (!is_directed_ and u > v)
6333 std::swap(u, v);
6334 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)
6335 : detail::undirected_edge_key(u, v));
6336 }
6337
6338 while (static_cast<int>(edges.size()) < m_) {
6339 std::pair<int, int> edge;
6340 if (!detail::try_generate_distinct(seen, [&] {
6341 edge = detail::get_random_graph_edge(n_, is_directed_,
6342 has_self_loops_);
6343 if (!is_directed_ and edge.first > edge.second)
6344 std::swap(edge.first, edge.second);
6345 return is_directed_ ? detail::directed_edge_key(edge.first,
6346 edge.second)
6347 : detail::undirected_edge_key(
6348 edge.first, edge.second);
6349 }))
6350 throw detail::error("wgraph: not enough edges to generate");
6351 edges.emplace_back(edge);
6352 }
6353
6354 return value(n_, edges, is_directed_);
6355 }
6356};
6357
6358// Implementation of wtree::value constructor from wgraph.
6359// O(n + m alpha(n)).
6360template <typename VWeight, typename EWeight>
6361wtree<VWeight, EWeight>::value::value(
6362 const typename wgraph<VWeight, EWeight>::value &g)
6363 : n_(g.n()), adj_(g.n()), print_1_based_(false), print_n_(false),
6364 dsu_(g.n()) {
6365 tgen_ensure(g.n() > 0, "wtree: value: graph must have at least one vertex");
6366 tgen_ensure(!g.is_directed(),
6367 "wtree: value: graph must be undirected to form a tree");
6368
6369 if (g.vertex_weights().has_value())
6370 vertex_weights_ = *g.vertex_weights();
6371 if (g.edge_weights().has_value())
6372 edge_weights_ = std::vector<EWeight>();
6373
6374 if (n_ == 1)
6375 return;
6376
6377 std::vector<int> order(g.m());
6378 std::iota(order.begin(), order.end(), 0);
6379 tgen::shuffle(order.begin(), order.end());
6380
6381 std::vector<std::pair<int, int>> tree_edges;
6382 tree_edges.reserve(n_ - 1);
6383
6384 for (int i : order) {
6385 auto [u, v] = g.edges()[i];
6386 if (!dsu_.unite(u, v))
6387 continue;
6388 if (u > v)
6389 std::swap(u, v);
6390
6391 tree_edges.emplace_back(u, v);
6392 adj_[u].insert(v);
6393 adj_[v].insert(u);
6394 if (edge_weights_.has_value())
6395 edge_weights_->push_back((*g.edge_weights())[i]);
6396 if (static_cast<int>(tree_edges.size()) == n_ - 1)
6397 break;
6398 }
6399
6400 tgen_ensure(static_cast<int>(tree_edges.size()) == n_ - 1,
6401 "wtree: value: graph must be connected to form a tree");
6402
6403 edges_ = std::move(tree_edges);
6404}
6405
6406/*
6407 * Other types of weighted-ness.
6408 */
6409
6410// Vertex weighted graph.
6411template <typename VWeight> using vgraph = wgraph<VWeight, int>;
6412
6413// Edge weighted graph.
6414template <typename EWeight> using egraph = wgraph<int, EWeight>;
6415
6416// Unweighted graph.
6417using graph = wgraph<int, int>;
6418
6419/*
6420 * Standard graphs.
6421 */
6422
6423// Complete.
6424// O(n^2).
6425inline graph::value K(int n) { return graph(n, n * (n - 1) / 2).gen(); }
6426
6427// Path.
6428// Path with `n` vertices. The edges of the path are 0 and n-1.
6429// If directed, edges are i -> i+1 for i in [0, n-2).
6430// O(n).
6431inline graph::value P(int n, bool is_directed = false) {
6432 graph g(n, n - 1, is_directed);
6433 for (int i = 0; i + 1 < n; ++i)
6434 g.add_edge(i, i + 1);
6435 return g.gen();
6436}
6437
6438// Cycle.
6439// n >= 3.
6440// If directed, edges are i -> (i+1) % n.
6441// O(n).
6442inline graph::value C(int n, bool is_directed = false) {
6443 tgen_ensure(n >= 3, "graph: cycle size must be at least 3");
6444
6445 graph g(n, n, is_directed);
6446 for (int i = 0; i < n; ++i)
6447 g.add_edge(i, (i + 1) % n);
6448 return g.gen();
6449}
6450
6451// Complete bipartite.
6452// The first side has vertices `0` to `n1-1`, the second side has vertices `n1`
6453// to `n1+n2-1`.
6454// O(n1 * n2).
6455inline graph::value K(int n1, int n2) {
6456 graph g(n1 + n2, static_cast<long long>(n1) * n2);
6457 for (int i = 0; i < n1; ++i)
6458 for (int j = 0; j < n2; ++j)
6459 g.add_edge(i, n1 + j);
6460 return g.gen();
6461}
6462
6463// Star.
6464// The center is vertex 0.
6465// O(n).
6466inline graph::value S(int n) { return K(1, n - 1); }
6467
6468/****************
6469 * *
6470 * GEOMETRY *
6471 * *
6472 ****************/
6473
6474namespace geometry {
6475
6476// Point on the plane with coordinates of type T.
6477template <typename T> struct point {
6478 static_assert(std::is_arithmetic_v<T>,
6479 "point requires an arithmetic coordinate type");
6480
6481 // Dot/cross product type: __int128 for T = long long, long long for other
6482 // integral T, T for floating-point.
6483 using product_t = std::conditional_t<
6484 std::is_same_v<T, long long>, detail::i128,
6485 std::conditional_t<std::is_integral_v<T>, long long, T>>;
6486
6487 // x and y coordinates.
6488 T x_, y_;
6489
6490 // Constructs a point with coordinates x and y.
6491 point(T x = 0, T y = 0) : x_(x), y_(y) {}
6492
6493 // Returns the x coordinate.
6494 T x() const { return x_; }
6495
6496 // Returns the y coordinate.
6497 T y() const { return y_; }
6498
6499 // Equality of coordinates, with epsilon-based equality for floating-point
6500 // coordinates (tolerance 1e-9).
6501 static bool coord_eq(T a, T b) {
6502 if constexpr (std::is_integral_v<T>)
6503 return a == b;
6504 constexpr T eps = T(1e-9);
6505 T d = a - b;
6506 return d >= -eps and d <= eps;
6507 }
6508
6509 // Lexicographic order (by x, then y).
6510 bool operator<(const point &p) const {
6511 if (!coord_eq(x_, p.x()))
6512 return x_ < p.x();
6513 return y_ < p.y();
6514 }
6515
6516 // Equality of coordinates.
6517 bool operator==(const point &p) const {
6518 return coord_eq(x_, p.x()) and coord_eq(y_, p.y());
6519 }
6520
6521 // Vector addition.
6522 point operator+(const point &p) const {
6523 return point(x_ + p.x(), y_ + p.y());
6524 }
6525
6526 // Vector subtraction.
6527 point operator-(const point &p) const {
6528 return point(x_ - p.x(), y_ - p.y());
6529 }
6530
6531 // Scalar multiplication.
6532 point operator*(T c) const { return point(x_ * c, y_ * c); }
6533
6534 // Dot product.
6535 product_t operator*(const point &p) const {
6536 if constexpr (std::is_floating_point_v<T>)
6537 return x_ * p.x() + y_ * p.y();
6538 return product_t(x_) * p.x() + product_t(y_) * p.y();
6539 }
6540
6541 // Cross product (signed area of the parallelogram).
6542 product_t operator^(const point &p) const {
6543 if constexpr (std::is_floating_point_v<T>)
6544 return x_ * p.y() - y_ * p.x();
6545 return product_t(x_) * p.y() - product_t(y_) * p.x();
6546 }
6547
6548 // Prints the point as "x y".
6549 friend std::ostream &operator<<(std::ostream &out, const point &p) {
6550 return out << p.x() << ' ' << p.y();
6551 }
6552};
6553
6554// Generates n distinct integer points in [min_coord, max_coord]^2 with no three
6555// collinear.
6556// O(n).
6557inline std::vector<point<long long>>
6558random_points_general_position(int n, long long min_coord,
6559 long long max_coord) {
6560 tgen_ensure(n > 0,
6561 "geometry: random_points_general_position: n must be positive");
6562 tgen_ensure(max_coord >= min_coord,
6563 "geometry: random_points_general_position: min_coord must be "
6564 "at most max_coord");
6566 static_cast<detail::i128>(max_coord) - min_coord <=
6567 std::numeric_limits<long long>::max(),
6568 "geometry: random_points_general_position: coordinate range too large");
6569 uint64_t width = max_coord - min_coord;
6570 uint64_t p = math::prime_from(2 * n);
6571
6572 // Requires width >= p - 1 because sheared coordinates lie in [0, p - 1].
6573 tgen_ensure(width >= p - 1,
6574 "geometry: random_points_general_position: coordinate range "
6575 "too small for n");
6576
6577 // Base set: (x, x^-1 mod p) for x = 1, ..., p - 1.
6578 //
6579 // For a line ax + by + c = 0, substituting y = x^-1 gives ax^2 + cx + b = 0
6580 // (for x != 0), a quadratic with at most two roots in F_p. So at most two
6581 // base points lie on any line. x |-> x^-1 is bijective on {1, ..., p - 1},
6582 // so all points are distinct and no three are collinear.
6583 std::vector<uint64_t> x_range(p - 1);
6584 std::iota(x_range.begin(), x_range.end(), 1);
6585 shuffle(x_range.begin(), x_range.end());
6586 std::vector<detail::i128> bx(n), by(n);
6587 for (int i = 0; i < n; ++i) {
6588 uint64_t x = x_range[i];
6589 bx[i] = x;
6590 by[i] = math::modular_inverse(x, p);
6591 }
6592
6593 // Randomize placement without breaking general position: compose elementary
6594 // shears in SL(2, F_p), each either [1 r; 0 1] or [1 0; r 1] with
6595 // r in {-2, -1, 1, 2} (mod p). Every shear has determinant 1, so their
6596 // product is invertible. Invertible linear maps preserve collinearity, so
6597 // the image still has no three collinear points.
6598 const int num_shears = 8;
6599 std::vector<detail::i128> lin_x = bx, lin_y = by;
6600
6601 for (int it = 0; it < num_shears; ++it) {
6602 bool vertical_shear = next(2) == 0;
6603 int shear_r = pick({-2, -1, 1, 2});
6604
6605 for (int i = 0; i < n; ++i) {
6606 if (vertical_shear)
6607 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;
6608 else
6609 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;
6610
6611 if (lin_x[i] < 0)
6612 lin_x[i] += p;
6613 if (lin_y[i] < 0)
6614 lin_y[i] += p;
6615 }
6616 }
6617
6618 detail::i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0],
6619 max_y = lin_y[0];
6620 for (int i = 1; i < n; ++i) {
6621 min_x = std::min(min_x, lin_x[i]);
6622 max_x = std::max(max_x, lin_x[i]);
6623 min_y = std::min(min_y, lin_y[i]);
6624 max_y = std::max(max_y, lin_y[i]);
6625 }
6626
6627 long long x_shift =
6628 min_coord - min_x + next<long long>(0, width - (max_x - min_x));
6629 long long y_shift =
6630 min_coord - min_y + next<long long>(0, width - (max_y - min_y));
6631
6632 std::vector<point<long long>> pts;
6633 for (int i = 0; i < n; ++i)
6634 pts.emplace_back(lin_x[i] + x_shift, lin_y[i] + y_shift);
6635 return pts;
6636}
6637
6638namespace detail {
6639
6640using i128 = tgen::detail::i128;
6641
6642// Signed area of triangle (a, b, p); positive iff (a, b, p) are in
6643// counterclockwise order. 0 iff (a, b, p) are collinear. O(1).
6644inline i128 ccw(const point<long long> &a, const point<long long> &b,
6645 const point<long long> &p) {
6646 return (static_cast<i128>(b.x()) - a.x()) *
6647 (static_cast<i128>(p.y()) - a.y()) -
6648 (static_cast<i128>(b.y()) - a.y()) *
6649 (static_cast<i128>(p.x()) - a.x());
6650}
6651
6652// Integer projection of P onto line AB (A and B need not be distinct).
6653inline i128 proj_on_ab(const point<long long> &P, const point<long long> &A,
6654 const point<long long> &B) {
6655 return (P - A) * (B - A);
6656}
6657
6658// In-place Hamiltonian path on points[left..right-1] with points[left]
6659// start and points[right-1] end.
6660// O(n log n) expected if points are "random", O(n^2) worst case.
6661inline void conquer(std::vector<point<long long>> &points, int left,
6662 int right) {
6663 if (right - left <= 3)
6664 return;
6665
6666 point<long long> A = points[left], B = points[right - 1];
6667
6668 // If all points are collinear, sort them properly and return.
6669 bool all_collinear = true;
6670 for (int k = left + 1; k < right - 1; ++k) {
6671 if (ccw(A, B, points[k]) != 0) {
6672 all_collinear = false;
6673 break;
6674 }
6675 }
6676 if (all_collinear) {
6677 std::sort(points.begin() + left, points.begin() + right,
6678 [&](const point<long long> &P, const point<long long> &Q) {
6679 return proj_on_ab(P, A, B) < proj_on_ab(Q, A, B);
6680 });
6681 return;
6682 }
6683
6684 // Choses a pivot that is not collinear with A and B.
6685 std::vector<int> candidates;
6686 for (int k = left + 1; k < right - 1; ++k) {
6687 if (ccw(A, B, points[k]) != 0)
6688 candidates.push_back(k);
6689 }
6690 int ci = candidates[next(0, static_cast<int>(candidates.size()) - 1)];
6691 point<long long> C = points[ci];
6692
6693 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6694 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6695 bool a_on_positive = ccw(C, A, B) < 0;
6696
6697 // Classify interior points into two sides of the wedge A-C-B for partition.
6698 // Collinear points on AB are tie-broken along the segment.
6699 i128 proj_sum = proj_on_ab(A, A, B) + proj_on_ab(B, A, B);
6700 auto is_positive = [&](const point<long long> &P) -> bool {
6701 i128 s = wa * ccw(C, A, P) + wb * ccw(C, B, P);
6702 // Weighted wedge side of P w.r.t. C, A, B.
6703 if (s != 0)
6704 return s > 0;
6705 // P is on line AB: split by projection past the midpoint.
6706 return 2 * proj_on_ab(P, A, B) > proj_sum;
6707 };
6708
6709 // Holds C at points[right-2] while classifying interior points in
6710 // [left+1, right-3].
6711 if (ci != right - 2)
6712 std::swap(points[ci], points[right - 2]);
6713
6714 int i = left + 1;
6715 int j = right - 3;
6716 while (i < j) {
6717 if (is_positive(points[i]) == a_on_positive)
6718 ++i;
6719 else if (is_positive(points[j]) != a_on_positive)
6720 --j;
6721 else {
6722 std::swap(points[i], points[j]);
6723 ++i;
6724 --j;
6725 }
6726 }
6727
6728 // After partition:
6729 // points[left]=A | (A,C)... | C | (C,B)... | points[right-1]=B.
6730
6731 // After the swap, p is the index of C (pivot between the two subpaths).
6732 int p = i;
6733 if (i == j and is_positive(points[i]) == a_on_positive)
6734 ++p;
6735 std::swap(points[p], points[right - 2]);
6736
6737 // Path A -> C.
6738 conquer(points, left, p + 1);
6739 // Path C -> B.
6740 conquer(points, p, right);
6741}
6742
6743// Samples k sorted distinct integers from [left, right] uniformly.
6744// Optimized for performance (pool partial Fisher–Yates or complement path for
6745// modest ranges; sparse-map fallback otherwise).
6746// O(k log k); O(right - left) memory when the range is modest.
6747inline std::vector<long long>
6748sample_sorted_distinct_in_range(int k, long long left, long long right) {
6749 long long universe = right - left + 1;
6750 std::vector<long long> res;
6751 res.reserve(k);
6752 if (k == 0)
6753 return res;
6754
6755 constexpr long long pool_threshold = 8'000'000;
6756 constexpr long long pool_always_below = 500'000;
6757
6758 if (universe <= pool_threshold and
6759 (universe <= pool_always_below or k >= universe / 4)) {
6760 size_t u = universe;
6761 size_t ks = k;
6762 std::vector<long long> pool(u);
6763 std::iota(pool.begin(), pool.end(), left);
6764 size_t m = ks <= u / 2 ? ks : u - ks;
6765 for (size_t i = 0; i < m; ++i) {
6766 size_t j = next<size_t>(i, u - 1);
6767 std::swap(pool[i], pool[j]);
6768 }
6769 if (ks <= u / 2) {
6770 res.assign(pool.begin(), pool.begin() + ks);
6771 std::sort(res.begin(), res.end());
6772 } else {
6773 std::vector<char> excluded(u, 0);
6774 for (size_t i = 0; i < m; ++i)
6775 excluded[pool[i] - left] = 1;
6776 for (long long v = left; v <= right; ++v)
6777 if (!excluded[v - left])
6778 res.push_back(v);
6779 }
6780 } else {
6781 std::unordered_map<long long, long long> virtual_list;
6782 virtual_list.reserve(k * 2);
6783 for (long long i = 0; i < k; ++i) {
6784 long long j = next<long long>(i, universe - 1);
6785 long long vi = virtual_list.count(i) ? virtual_list[i] : i;
6786 long long vj = virtual_list.count(j) ? virtual_list[j] : j;
6787 virtual_list[j] = vi;
6788 virtual_list[i] = vj;
6789 res.push_back(virtual_list[i] + left);
6790 }
6791 std::sort(res.begin(), res.end());
6792 }
6793 return res;
6794}
6795
6796// Valtr-style signed edge components along one axis from n sorted distinct
6797// coordinates. The n differences sum to zero.
6798inline std::vector<long long>
6799valtr_edge_components(const std::vector<long long> &sorted_coords) {
6800 int n = sorted_coords.size();
6801 std::vector<long long> left, right;
6802 left.reserve(n / 2);
6803 right.reserve(n / 2);
6804 for (int i = 1; i + 1 < n; ++i) {
6805 if (next(2) == 0)
6806 left.push_back(sorted_coords[i]);
6807 else
6808 right.push_back(sorted_coords[i]);
6809 }
6810 long long lo = sorted_coords.front(), hi = sorted_coords.back();
6811 std::vector<long long> seq;
6812 seq.reserve(n + 1);
6813 seq.push_back(lo);
6814 for (long long v : left)
6815 seq.push_back(v);
6816 seq.push_back(hi);
6817 for (auto it = right.rbegin(); it != right.rend(); ++it)
6818 seq.push_back(*it);
6819 seq.push_back(lo);
6820 std::vector<long long> comps(n);
6821 for (int i = 0; i < n; ++i)
6822 comps[i] = seq[i + 1] - seq[i];
6823 return comps;
6824}
6825
6826// Drops boundary vertices that are collinear with their cyclic neighbors.
6827// O(m), m = |points|.
6828inline std::vector<point<long long>>
6829simplify_strict_boundary(std::vector<point<long long>> points) {
6830 int n = points.size();
6831 if (n < 3)
6832 return points;
6833
6834 std::vector<point<long long>> strict_points;
6835 strict_points.reserve(n);
6836 for (int i = 0; i < n; ++i) {
6837 if (ccw(points[(i + n - 1) % n], points[i], points[(i + 1) % n]) != 0)
6838 strict_points.push_back(points[i]);
6839 }
6840 return strict_points;
6841}
6842
6843// Picks k evenly spaced vertices along a longer cyclic boundary.
6844// O(k).
6845inline std::vector<point<long long>>
6846subsample_boundary(const std::vector<point<long long>> &points, int k) {
6847 int n = points.size();
6848 if (n <= k)
6849 return points;
6850
6851 std::vector<point<long long>> sampled_points;
6852 sampled_points.reserve(k);
6853 for (int i = 0; i < k; ++i)
6854 sampled_points.push_back(points[(static_cast<i128>(i) * n) / k]);
6855 return sampled_points;
6856}
6857
6858// Random translation so the polygon lies in the box.
6859// O(|points|).
6860inline void place_inside_box(std::vector<point<long long>> &points,
6861 long long min_coord, long long max_coord) {
6862 long long width = max_coord - min_coord + 1;
6863
6864 i128 min_x = points[0].x(), max_x = points[0].x();
6865 i128 min_y = points[0].y(), max_y = points[0].y();
6866 for (const point<long long> &p : points) {
6867 min_x = std::min(min_x, static_cast<i128>(p.x()));
6868 max_x = std::max(max_x, static_cast<i128>(p.x()));
6869 min_y = std::min(min_y, static_cast<i128>(p.y()));
6870 max_y = std::max(max_y, static_cast<i128>(p.y()));
6871 }
6872
6873 i128 span_x = max_x - min_x;
6874 i128 span_y = max_y - min_y;
6875 // Random slack keeps the polygon inside the box without filling it.
6876 i128 shift_x =
6877 min_coord - min_x +
6878 next<long long>(0, width - 1 - static_cast<long long>(span_x));
6879 i128 shift_y =
6880 min_coord - min_y +
6881 next<long long>(0, width - 1 - static_cast<long long>(span_y));
6882
6883 for (point<long long> &p : points)
6884 p = point<long long>(p.x() + shift_x, p.y() + shift_y);
6885}
6886
6887// Random cyclic shift.
6888// O(|points|).
6889inline void randomize_cyclic_shift(std::vector<point<long long>> &points) {
6890 int rot = next(points.size());
6891 if (rot > 0)
6892 std::rotate(points.begin(), points.begin() + rot, points.end());
6893}
6894
6895// Valtr walk for m edges; bbox minimum translated to the origin.
6896// O(m log m).
6897inline std::vector<point<long long>>
6898valtr_vertices(int m, const std::vector<long long> &x_comp,
6899 std::vector<long long> y_comp) {
6900 shuffle(y_comp.begin(), y_comp.end());
6901
6902 std::vector<point<long long>> edges(m);
6903 // Upper half-plane (positive y, or y = 0 and x > 0) sorts before lower.
6904 auto upper = [](const point<long long> &p) {
6905 return p.y() > 0 or (p.y() == 0 and p.x() > 0);
6906 };
6907 for (int i = 0; i < m; ++i)
6908 edges[i] = point<long long>(x_comp[i], y_comp[i]);
6909
6910 std::sort(edges.begin(), edges.end(),
6911 [&upper](const point<long long> &a, const point<long long> &b) {
6912 bool au = upper(a), bu = upper(b);
6913 if (au != bu)
6914 return au;
6915 auto cross = a ^ b;
6916 if (cross != 0)
6917 return cross > 0;
6918 return (a * a) < (b * b);
6919 });
6920
6921 // Prefix-sum the sorted edge vectors to obtain vertex coordinates.
6922 i128 cur_x = 0, cur_y = 0;
6923 std::vector<i128> px(m), py(m);
6924 for (int i = 0; i < m; ++i) {
6925 px[i] = cur_x;
6926 py[i] = cur_y;
6927 cur_x += edges[i].x();
6928 cur_y += edges[i].y();
6929 }
6930 tgen::detail::tgen_ensure_against_bug(
6931 cur_x == 0 and cur_y == 0,
6932 "geometry: random_convex_polygon: walk did not close");
6933
6934 i128 min_x = px[0], min_y = py[0];
6935 for (int i = 1; i < m; ++i) {
6936 min_x = std::min(min_x, px[i]);
6937 min_y = std::min(min_y, py[i]);
6938 }
6939
6940 // Shift so the bbox minimum is at the origin.
6941 std::vector<point<long long>> points;
6942 points.reserve(m);
6943 for (int i = 0; i < m; ++i)
6944 points.emplace_back(px[i] - min_x, py[i] - min_y);
6945 return points;
6946}
6947
6948} // namespace detail
6949
6950// Generates n vertices of a convex integer polygon inside a box.
6951// If strict is true, boundary vertices are guaranteed non-collinear when
6952// generation succeeds; retry count depends on n and width.
6953// Always returns points in counterclockwise order.
6954// O(n log n).
6955inline std::vector<point<long long>>
6956random_convex_polygon(int n, long long min_coord, long long max_coord,
6957 bool strict = false) {
6958 tgen_ensure(n >= 3,
6959 "geometry: random_convex_polygon: n must be at least 3");
6960 tgen_ensure(max_coord >= min_coord,
6961 "geometry: random_convex_polygon: min_coord must be at most "
6962 "max_coord");
6963 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord + 1 <=
6964 std::numeric_limits<long long>::max(),
6965 "geometry: random_convex_polygon: coordinate range too large");
6966 long long width = max_coord - min_coord + 1;
6968 width >= n,
6969 "geometry: random_convex_polygon: coordinate range too small for n");
6970
6971 // Valtr walk size: n in weak mode; strict mode uses a larger grid so
6972 // collinear removal still leaves at least n vertices to subsample.
6973 int num_coords = n;
6974 if (strict) {
6975 // Extra grid lines beyond n: at least 100 (small-n headroom), about
6976 // n/1000 for large n, and never more than width - n.
6977 int extra = width <= n ? 0
6978 : std::min<long long>(std::max(100, n / 1000),
6979 width - n);
6980 num_coords = n + extra;
6981 }
6982
6983 // Strict mode retries coordinate sampling when simplification leaves < n
6984 // vertices; weak mode has no failure path, so one attempt always suffices.
6985 const int max_attempts = strict ? 32 : 1;
6986 for (int i = 0; i < max_attempts; ++i) {
6987 // Build a convex lattice polygon on [0, width - 1]^2, then translate.
6988 std::vector<long long> x_sorted =
6989 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6990 std::vector<long long> y_sorted =
6991 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6992 std::vector<long long> x_comp = detail::valtr_edge_components(x_sorted);
6993 std::vector<long long> y_comp = detail::valtr_edge_components(y_sorted);
6994
6995 std::vector<point<long long>> points =
6996 detail::valtr_vertices(num_coords, x_comp, std::move(y_comp));
6997
6998 if (strict) {
6999 std::vector<point<long long>> simplified =
7000 detail::simplify_strict_boundary(std::move(points));
7001 // Tight boxes can leave too few vertices -> resample coordinates.
7002 if (static_cast<int>(simplified.size()) < n)
7003 continue;
7004
7005 points = detail::subsample_boundary(simplified, n);
7006 }
7007
7008 detail::place_inside_box(points, min_coord, max_coord);
7009 detail::randomize_cyclic_shift(points);
7010 return points;
7011 }
7012
7013 // Generation failed.
7014 throw tgen::detail::error(
7015 "geometry: random_convex_polygon: generation failed: coordinate "
7016 "range too small for n");
7017}
7018
7019// Random simple polygon through given distinct points.
7020// Collinear triples are allowed; fails if all points are collinear.
7021// Always returns vertices in counterclockwise order.
7022// O(n log n) expected if points are "random", O(n^2) worst case.
7024 const std::vector<point<long long>> &points) {
7025 int n = points.size();
7026 tgen_ensure(n >= 3,
7027 "geometry: random_simple_polygon_through_points: need at "
7028 "least 3 points");
7030 static_cast<int>(
7031 std::set<point<long long>>(points.begin(), points.end()).size()) ==
7032 n,
7033 "geometry: random_simple_polygon_through_points: points must "
7034 "be distinct");
7035
7036 int idx_a = 0, idx_b = 0;
7037 for (int i = 1; i < n; ++i) {
7038 if (points[i] < points[idx_a])
7039 idx_a = i;
7040 if (points[idx_b] < points[i])
7041 idx_b = i;
7042 }
7043 point<long long> A = points[idx_a], B = points[idx_b];
7044
7045 bool all_collinear = true;
7046 for (int i = 0; i < n; ++i) {
7047 if (i == idx_a or i == idx_b)
7048 continue;
7049 if (detail::ccw(A, B, points[i]) != 0) {
7050 all_collinear = false;
7051 break;
7052 }
7053 }
7054 tgen_ensure(!all_collinear,
7055 "geometry: random_simple_polygon_through_points: all points "
7056 "are collinear; no simple polygon exists");
7057
7058 // Keep points collinear with AB on the chain that has no other points on
7059 // its side, so AB is split through those vertices instead of crossing them
7060 // later.
7061 int negative_count = 0;
7062 for (int i = 0; i < n; ++i) {
7063 if (i == idx_a or i == idx_b)
7064 continue;
7065 if (detail::ccw(A, B, points[i]) < 0)
7066 ++negative_count;
7067 }
7068
7069 std::vector<point<long long>> chain;
7070 chain.push_back(A);
7071 int left_count = 0;
7072 for (int i = 0; i < n; ++i) {
7073 if (i == idx_a or i == idx_b)
7074 continue;
7075 detail::i128 side = detail::ccw(A, B, points[i]);
7076 if (side < 0 or (side == 0 and negative_count == 0)) {
7077 chain.push_back(points[i]);
7078 ++left_count;
7079 }
7080 }
7081 chain.push_back(B);
7082 for (int i = 0; i < n; ++i) {
7083 if (i == idx_a or i == idx_b)
7084 continue;
7085 detail::i128 side = detail::ccw(A, B, points[i]);
7086 if (side > 0 or (side == 0 and negative_count != 0))
7087 chain.push_back(points[i]);
7088 }
7089 chain.push_back(A);
7090
7091 int n1 = 2 + left_count;
7092 // Upper chain: A -> B.
7093 detail::conquer(chain, 0, n1);
7094 // Lower chain: B -> A.
7095 detail::conquer(chain, n1 - 1, chain.size());
7096
7097 // Cyclic vertex order: chain[1..n1) then chain[n1..end) (skip each path's
7098 // start vertex).
7099 std::vector<point<long long>> poly;
7100 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);
7101 poly.insert(poly.end(), chain.begin() + n1, chain.end());
7102 return poly;
7103}
7104
7105namespace detail {
7106
7107// Samples n distinct integer points in [min_coord, max_coord]^2.
7108// O(n log n).
7109inline std::vector<point<long long>>
7110random_distinct_points_in_box(int n, long long min_coord, long long max_coord) {
7111 long long width = max_coord - min_coord;
7112 i128 side_128 = width + 1;
7113 i128 universe = side_128 * side_128;
7114 tgen_ensure(universe <= std::numeric_limits<long long>::max(),
7115 "geometry: random_simple_polygon: coordinate range too large");
7116 long long side = side_128;
7117 tgen_ensure(universe >= n,
7118 "geometry: random_simple_polygon: coordinate range too small "
7119 "for n distinct points");
7120
7121 // Decodes a linear grid key (x * side + y) to a point.
7122 auto decode = [&](long long key) -> point<long long> {
7123 return point<long long>(min_coord + key / side, min_coord + key % side);
7124 };
7125
7126 // Repeats until all generated points are not collinear.
7127 // Runs O(1) expected times.
7128 while (true) {
7129 std::vector<long long> keys =
7130 distinct_range<long long>(0, universe - 1).gen_list(n).to_std();
7131
7132 std::vector<point<long long>> points;
7133 points.reserve(n);
7134 for (long long key : keys)
7135 points.push_back(decode(key));
7136
7137 // Checks if the points are not all collinear.
7138 for (int i = 2; i < n; ++i) {
7139 if (ccw(points[0], points[1], points[i]) != 0)
7140 return points;
7141 }
7142 }
7143}
7144
7145// Axis-aligned edge data for a CCW polygon (interior on the left).
7146// O(1).
7147struct ortho_poly_edge {
7148 long long len;
7149 bool horiz;
7150 long long fixed;
7151 long long lo, hi;
7152 int out_x, out_y;
7153};
7154
7155// True if a, b, c lie on one horizontal or vertical line.
7156// O(1).
7157inline bool ortho_axis_collinear(const point<long long> &a,
7158 const point<long long> &b,
7159 const point<long long> &c) {
7160 return (a.x() == b.x() and b.x() == c.x()) or
7161 (a.y() == b.y() and b.y() == c.y());
7162}
7163
7164// Edge i of poly: orientation, span, exterior normal.
7165// O(1).
7166inline ortho_poly_edge
7167ortho_analyze_edge(const std::vector<point<long long>> &poly, int i) {
7168 int m = poly.size();
7169 point<long long> a = poly[i], b = poly[(i + 1) % m];
7170 ortho_poly_edge e{};
7171 if (a.y() == b.y()) {
7172 e.horiz = true;
7173 e.fixed = a.y();
7174 e.lo = std::min(a.x(), b.x());
7175 e.hi = std::max(a.x(), b.x());
7176 e.out_x = 0;
7177 e.out_y = a.x() < b.x() ? -1 : 1;
7178 } else {
7179 e.fixed = a.x();
7180 e.lo = std::min(a.y(), b.y());
7181 e.hi = std::max(a.y(), b.y());
7182 e.out_x = a.y() < b.y() ? 1 : -1;
7183 }
7184 e.len = e.hi - e.lo;
7185 return e;
7186}
7187
7188// True if open axis-aligned segments (a, b) and (c, d) properly cross or
7189// overlap (excluding shared endpoints).
7190// O(1).
7191inline bool ortho_open_seg_cross(const point<long long> &a,
7192 const point<long long> &b,
7193 const point<long long> &c,
7194 const point<long long> &d) {
7195 if (a.y() == b.y() and c.y() == d.y()) {
7196 if (a.y() != c.y())
7197 return false;
7198 long long lo1 = std::min(a.x(), b.x()), hi1 = std::max(a.x(), b.x());
7199 long long lo2 = std::min(c.x(), d.x()), hi2 = std::max(c.x(), d.x());
7200 return lo1 < hi2 and lo2 < hi1;
7201 }
7202 if (a.x() == b.x() and c.x() == d.x()) {
7203 if (a.x() != c.x())
7204 return false;
7205 long long lo1 = std::min(a.y(), b.y()), hi1 = std::max(a.y(), b.y());
7206 long long lo2 = std::min(c.y(), d.y()), hi2 = std::max(c.y(), d.y());
7207 return lo1 < hi2 and lo2 < hi1;
7208 }
7209 if (a.y() == b.y() and c.x() == d.x()) {
7210 long long hx = a.y(), vx = c.x();
7211 long long hlo = std::min(a.x(), b.x()), hhi = std::max(a.x(), b.x());
7212 long long vlo = std::min(c.y(), d.y()), vhi = std::max(c.y(), d.y());
7213 return hlo < vx and vx < hhi and vlo < hx and hx < vhi;
7214 }
7215 if (a.x() == b.x() and c.y() == d.y()) {
7216 long long vx = a.x(), hy = c.y();
7217 long long vlo = std::min(a.y(), b.y()), vhi = std::max(a.y(), b.y());
7218 long long hlo = std::min(c.x(), d.x()), hhi = std::max(c.x(), d.x());
7219 return vlo < hy and hy < vhi and hlo < vx and vx < hhi;
7220 }
7221 return false;
7222}
7223
7224// Integral ray-crossing point-in-polygon.
7225// O(|poly|).
7226inline bool ortho_point_inside(const std::vector<point<long long>> &poly,
7227 point<long long> p) {
7228 int m = poly.size();
7229 bool inside = false;
7230 for (int i = 0, j = m - 1; i < m; j = i++) {
7231 point<long long> a = poly[i], b = poly[j];
7232 if ((a.y() > p.y()) != (b.y() > p.y())) {
7233 i128 x_cross = i128(b.x() - a.x()) * (p.y() - a.y()) -
7234 i128(p.x() - a.x()) * (b.y() - a.y());
7235 if ((a.y() < b.y()) ? x_cross > 0 : x_cross < 0)
7236 inside = !inside;
7237 }
7238 }
7239 return inside;
7240}
7241
7242// True if p lies strictly in the open segment (a, b).
7243// O(1).
7244inline bool ortho_point_strictly_interior(point<long long> p,
7245 point<long long> a,
7246 point<long long> b) {
7247 if (a.y() == b.y()) {
7248 if (p.y() != a.y())
7249 return false;
7250 long long lo = std::min(a.x(), b.x()), hi = std::max(a.x(), b.x());
7251 return lo < p.x() and p.x() < hi;
7252 }
7253 if (a.x() == b.x()) {
7254 if (p.x() != a.x())
7255 return false;
7256 long long lo = std::min(a.y(), b.y()), hi = std::max(a.y(), b.y());
7257 return lo < p.y() and p.y() < hi;
7258 }
7259 return false;
7260}
7261
7262// True if p lies on the closed segment [a, b].
7263// O(1).
7264inline bool ortho_point_on_segment(point<long long> p, point<long long> a,
7265 point<long long> b) {
7266 return p == a or p == b or ortho_point_strictly_interior(p, a, b);
7267}
7268
7269// True if splicing add between A and B on edge_i is valid: no vertex of add
7270// coincides with poly, no boundary self-contact (forward or reverse
7271// T-junctions, collinear overlaps), new segments do not cross other boundary
7272// edges, and inward notches keep all of add inside poly.
7273// O(|poly|), assuming |add| is O(1).
7274inline bool ortho_bump_valid(const std::vector<point<long long>> &poly,
7275 point<long long> A, point<long long> B,
7276 const std::vector<point<long long>> &add,
7277 int edge_i, bool inward) {
7278 int m = poly.size();
7279
7280 for (point<long long> v : add)
7281 for (point<long long> q : poly)
7282 if (v == q)
7283 return false;
7284
7285 // Forward T-junction: new vertex on a non-incident edge interior, or on
7286 // edge_i but outside the replaced subsegment [A, B].
7287 for (point<long long> v : add) {
7288 for (int j = 0; j < m; ++j) {
7289 point<long long> c = poly[j], d = poly[(j + 1) % m];
7290 if (j == edge_i) {
7291 if (ortho_point_on_segment(v, c, d) and
7292 !ortho_point_on_segment(v, A, B))
7293 return false;
7294 } else if (ortho_point_strictly_interior(v, c, d)) {
7295 return false;
7296 }
7297 }
7298 }
7299
7300 auto seg_ok = [&](point<long long> s0, point<long long> s1) {
7301 for (int j = 0; j < m; ++j) {
7302 if (j == edge_i)
7303 continue;
7304 point<long long> c = poly[j], d = poly[(j + 1) % m];
7305 if (ortho_open_seg_cross(s0, s1, c, d))
7306 return false;
7307 }
7308 for (int k = 0; k < m; ++k) {
7309 point<long long> q = poly[k];
7310 if (q == s0 or q == s1 or q == A or q == B)
7311 continue;
7312 if (ortho_point_strictly_interior(q, s0, s1))
7313 return false;
7314 }
7315 return true;
7316 };
7317
7318 point<long long> prev = A;
7319 for (point<long long> v : add) {
7320 if (!seg_ok(prev, v))
7321 return false;
7322 prev = v;
7323 }
7324 if (!seg_ok(prev, B))
7325 return false;
7326
7327 if (inward) {
7328 for (point<long long> v : add)
7329 if (!ortho_point_inside(poly, v))
7330 return false;
7331 }
7332
7333 return true;
7334}
7335
7336// Splices a rectangular tab or notch on edge edge_i over [lo, hi], extending
7337// depth units perpendicular to the edge.
7338// O(|poly|).
7339inline bool ortho_bump_edge(std::vector<point<long long>> &poly, int edge_i,
7340 const ortho_poly_edge &e, long long lo,
7341 long long hi, long long depth, bool inward,
7342 size_t max_vertices) {
7343 int m = poly.size();
7344 point<long long> A = poly[edge_i], B = poly[(edge_i + 1) % m];
7345
7346 int step_x = inward ? -e.out_x : e.out_x;
7347 int step_y = inward ? -e.out_y : e.out_y;
7348
7349 std::vector<point<long long>> add;
7350 if (e.horiz) {
7351 long long y = e.fixed, y2 = y + step_y * depth;
7352 if (A.x() < B.x()) {
7353 if (lo > A.x())
7354 add.emplace_back(lo, y);
7355 add.emplace_back(lo, y2);
7356 add.emplace_back(hi, y2);
7357 if (hi < B.x())
7358 add.emplace_back(hi, y);
7359 } else {
7360 if (hi < A.x())
7361 add.emplace_back(hi, y);
7362 add.emplace_back(hi, y2);
7363 add.emplace_back(lo, y2);
7364 if (lo > B.x())
7365 add.emplace_back(lo, y);
7366 }
7367 } else {
7368 long long x = e.fixed, x2 = x + step_x * depth;
7369 if (A.y() < B.y()) {
7370 if (lo > A.y())
7371 add.emplace_back(x, lo);
7372 add.emplace_back(x2, lo);
7373 add.emplace_back(x2, hi);
7374 if (hi < B.y())
7375 add.emplace_back(x, hi);
7376 } else {
7377 if (hi < A.y())
7378 add.emplace_back(x, hi);
7379 add.emplace_back(x2, hi);
7380 add.emplace_back(x2, lo);
7381 if (lo > B.y())
7382 add.emplace_back(x, lo);
7383 }
7384 }
7385 if (poly.size() > max_vertices or add.size() > max_vertices - poly.size())
7386 return false;
7387 if (!ortho_bump_valid(poly, A, B, add, edge_i, inward))
7388 return false;
7389
7390 poly.insert(poly.begin() + edge_i + 1, add.begin(), add.end());
7391 return true;
7392}
7393
7394// Picks edge i with probability proportional to
7395// e.len * (4 + min(global_timestamp - last_used[i], 8)).
7396// O(|poly|).
7397inline int ortho_pick_poly_edge(const std::vector<point<long long>> &poly,
7398 std::vector<int> &last_used, int &time_stamp) {
7399 int m = poly.size();
7400 if (last_used.size() != static_cast<size_t>(m)) {
7401 last_used.assign(m, 0);
7402 time_stamp = 0;
7403 }
7404 std::vector<long long> weights(m);
7405 long long total = 0;
7406 for (int i = 0; i < m; ++i) {
7407 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7408 weights[i] = e.len * (4 + std::min(time_stamp - last_used[i], 8));
7409 total += weights[i];
7410 }
7411 long long pick = next<long long>(0, total - 1);
7412 for (int i = 0; i < m; ++i) {
7413 pick -= weights[i];
7414 if (pick < 0) {
7415 last_used[i] = ++time_stamp;
7416 return i;
7417 }
7418 }
7419 last_used[m - 1] = ++time_stamp;
7420 return m - 1;
7421}
7422
7423// One random inflate/cut attempt.
7424// O(|poly|).
7425inline bool
7426ortho_try_bump(std::vector<point<long long>> &poly, int n,
7427 std::vector<int> &last_used, int &time_stamp,
7428 bool outward_only = false,
7429 size_t max_vertices = std::numeric_limits<size_t>::max()) {
7430 if (poly.size() < 3)
7431 return false;
7432
7433 int ei = ortho_pick_poly_edge(poly, last_used, time_stamp);
7434 ortho_poly_edge e = ortho_analyze_edge(poly, ei);
7435
7436 // Edge subdivision can leave length-1 segments; a tab needs span >= 2.
7437 if (e.len < 2)
7438 return false;
7439
7440 // Random subinterval [lo, lo + span] on the edge, with 2 <= span <= e.len.
7441 long long span = next<long long>(2, e.len);
7442 long long lo = next<long long>(e.lo, e.hi - span);
7443
7444 // max_depth: cap on perpendicular tab/notch height (~sqrt(n), in [2, 12]).
7445 // depth: actual height; shallow usually, up to max_depth 10% of the time.
7446 long long max_depth =
7447 std::clamp<long long>(std::sqrt(n) / 2 + 2, 2LL, 12LL);
7448 long long depth =
7449 next(10) == 0 ? next<long long>(std::max(2LL, max_depth / 2), max_depth)
7450 : next<long long>(1, std::max(2LL, max_depth / 3));
7451
7452 bool inward = !outward_only and next(4) == 0;
7453 return ortho_bump_edge(poly, ei, e, lo, lo + span, depth, inward,
7454 max_vertices);
7455}
7456
7457// Drops axis-aligned collinear vertices.
7458// O(n).
7459inline std::vector<point<long long>>
7460ortho_simplify_collinear(std::vector<point<long long>> poly) {
7461 int n = poly.size();
7462 if (n < 3)
7463 return poly;
7464 std::vector<point<long long>> out;
7465 out.reserve(n);
7466 for (int i = 0; i < n; ++i) {
7467 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7468 poly[(i + 1) % n]))
7469 out.push_back(poly[i]);
7470 }
7471 return out.size() >= 3 ? out : poly;
7472}
7473
7474// Removes one collinear vertex.
7475// O(n).
7476inline bool ortho_remove_one_collinear(std::vector<point<long long>> &poly) {
7477 int n = poly.size();
7478 if (n < 4)
7479 return false;
7480 for (int i = 0; i < n; ++i) {
7481 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7482 poly[(i + 1) % n]))
7483 continue;
7484 poly.erase(poly.begin() + i);
7485 return true;
7486 }
7487 return false;
7488}
7489
7490// Inserts collinear vertices on straight edges until size reaches `target` (or
7491// no edge has spare integer points). Preserves boundary order.
7492// O(target).
7493inline void ortho_fill_collinear(std::vector<point<long long>> &poly,
7494 int target) {
7495 int need = target - poly.size();
7496 if (need <= 0)
7497 return;
7498
7499 std::vector<point<long long>> out;
7500 int m = poly.size();
7501 out.reserve(poly.size() + need);
7502
7503 for (int i = 0; i < m; ++i) {
7504 point<long long> a = poly[i], b = poly[(i + 1) % m];
7505 out.push_back(a);
7506 if (need <= 0)
7507 continue;
7508
7509 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7510 long long cap = e.len - 1;
7511 if (cap <= 0)
7512 continue;
7513
7514 // Adds `take` collinear vertices to the boundary.
7515 long long take = std::min<long long>(need, cap);
7516 bool forward = e.horiz ? a.x() < b.x() : a.y() < b.y();
7517 for (long long k = 0; k < take; ++k) {
7518 long long off = (k + 1) * (cap + 1) / (take + 1);
7519 long long coord = forward ? e.lo + off : e.hi - off;
7520 if (e.horiz)
7521 out.push_back({coord, e.fixed});
7522 else
7523 out.push_back({e.fixed, coord});
7524 }
7525 need -= take;
7526 }
7527 poly.swap(out);
7528}
7529
7530// Inserts outward depth-1 corrugation tabs on straight edges until size reaches
7531// `target` (or no edge has room for another tab). Preserves boundary order.
7532// Assumes the scale-up step left every edge on a grid with spacing >= 4.
7533// Each tab perturbs a coordinate by 1 and keeps a >= 2 margin from both
7534// corners, so tabs can only meet tabs on the same or a directly facing edge.
7535// The result is therefore simple and free of collinear triples by construction.
7536// O(target).
7537inline void ortho_fill_corrugation(std::vector<point<long long>> &poly,
7538 size_t target) {
7539 size_t n_sz = poly.size();
7540 if (n_sz >= target)
7541 return;
7542
7543 size_t extra_left = target - n_sz;
7544
7545 std::vector<point<long long>> out;
7546 out.reserve(target);
7547 int n = poly.size();
7548
7549 for (int i = 0; i < n; ++i) {
7550 point<long long> a = poly[i], b = poly[(i + 1) % n];
7551 out.push_back(a);
7552
7553 if (extra_left < 4)
7554 continue;
7555
7556 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7557 if (e.len < 5)
7558 continue;
7559
7560 long long dir = (e.horiz ? a.x() < b.x() : a.y() < b.y()) ? 1 : -1;
7561 long long start = e.horiz ? a.x() : a.y();
7562 long long end = e.horiz ? b.x() : b.y();
7563
7564 for (long long pos = start + 2 * dir;
7565 extra_left >= 4 and (pos - end) * dir <= -3; pos += 2 * dir) {
7566 if (e.horiz) {
7567 long long y2 = e.fixed + e.out_y;
7568 out.push_back({pos, e.fixed});
7569 out.push_back({pos, y2});
7570 out.push_back({pos + dir, y2});
7571 out.push_back({pos + dir, e.fixed});
7572 } else {
7573 long long x2 = e.fixed + e.out_x;
7574 out.push_back({e.fixed, pos});
7575 out.push_back({x2, pos});
7576 out.push_back({x2, pos + dir});
7577 out.push_back({e.fixed, pos + dir});
7578 }
7579 extra_left -= 4;
7580 }
7581 }
7582
7583 poly.swap(out);
7584}
7585
7586// CCW square seed plus boundary inflate/cut to about n vertices.
7587// O(n^2) for n <= 1000; O(n) otherwise.
7588inline std::vector<point<long long>> build_orthogonal_polygon(int n,
7589 bool strict) {
7590 bool scale_up = n > 1000;
7591
7592 long long side = std::max<long long>(3, std::sqrt(n));
7593 if (scale_up)
7594 side = std::clamp(static_cast<long long>(2 * std::sqrt(std::sqrt(n))),
7595 8LL, 64LL);
7596 std::vector<point<long long>> poly = {
7597 {0, 0}, {side, 0}, {side, side}, {0, side}};
7598
7599 int target_ops = scale_up ? std::max(1, static_cast<int>(4 * side - 4) / 2)
7600 : std::max(1, (n - 4) / 2);
7601
7602 if (scale_up)
7603 target_ops = std::min(
7604 target_ops,
7605 400 + static_cast<int>(4 * std::sqrt(static_cast<double>(side))));
7606
7607 int failure_limit = std::min(target_ops * 8, 2000);
7608
7609 std::vector<int> last_used;
7610 int time_stamp = 0, consecutive_failures = 0;
7611 size_t max_vertices =
7612 scale_up ? std::numeric_limits<size_t>::max() : static_cast<size_t>(n);
7613 for (int ops = 0; ops < target_ops;) {
7614 if (!scale_up and poly.size() + 2 > static_cast<size_t>(n))
7615 break;
7616
7617 if (ortho_try_bump(poly, n, last_used, time_stamp, scale_up,
7618 max_vertices)) {
7619 ++ops;
7620 consecutive_failures = 0;
7621 } else if (++consecutive_failures >= failure_limit) {
7622 break;
7623 }
7624 }
7625 if (strict)
7626 poly = ortho_simplify_collinear(std::move(poly));
7627
7628 if (scale_up) {
7629 while (poly.size() > static_cast<size_t>(n) and
7630 ortho_remove_one_collinear(poly))
7631 ;
7632 long long upscale = std::max(4LL, ((n + 3) / 4 + side - 1) / side);
7633 for (point<long long> &p : poly)
7634 p = {p.x() * upscale, p.y() * upscale};
7635 if (strict)
7636 ortho_fill_corrugation(poly, n);
7637 else
7638 ortho_fill_collinear(poly, n);
7639 } else if (!strict)
7640 ortho_fill_collinear(poly, n);
7641
7642 return poly;
7643}
7644
7645} // namespace detail
7646
7647// Random simple polygon.
7648// If strict, vertex set has no three collinear points
7649// (random_points_general_position); otherwise samples distinct grid points
7650// (collinear triples allowed), so it might be the case that (polygon[i],
7651// polygon[i+1], and polygon[i+2]) are collinear. Polygonizes via
7652// random_simple_polygon_through_points. Always counterclockwise.
7653// O(n log n) expected.
7654inline std::vector<point<long long>>
7655random_simple_polygon(int n, long long min_coord, long long max_coord,
7656 bool strict = false) {
7657 tgen_ensure(n >= 3,
7658 "geometry: random_simple_polygon: n must be at least 3");
7659 tgen_ensure(max_coord >= min_coord,
7660 "geometry: random_simple_polygon: min_coord must be at most "
7661 "max_coord");
7662 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord <=
7663 std::numeric_limits<long long>::max(),
7664 "geometry: random_simple_polygon: coordinate range too large");
7665
7666 std::vector<point<long long>> points =
7667 strict ? random_points_general_position(n, min_coord, max_coord)
7668 : detail::random_distinct_points_in_box(n, min_coord, max_coord);
7669 return random_simple_polygon_through_points(points);
7670}
7671
7672// Random orthogonal simple polygon, CCW. Each local bump/scale/fill step
7673// preserves full simplicity, so the result is valid by construction.
7674// Exactly n vertices when !strict; at most n when strict (near n for n > 1000).
7675// O(n^2) for n <= 1000; O(n) otherwise.
7676inline std::vector<point<long long>>
7677random_orthogonal_polygon(int n, long long min_coord, long long max_coord,
7678 bool strict = false) {
7679 tgen_ensure(n >= 4,
7680 "geometry: random_orthogonal_polygon: n must be at least 4");
7681 tgen_ensure(max_coord >= min_coord,
7682 "geometry: random_orthogonal_polygon: min_coord must be at "
7683 "most max_coord");
7684 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7685 std::numeric_limits<long long>::max(),
7686 "geometry: random_orthogonal_polygon: coordinate range too "
7687 "large");
7688 long long width = max_coord - min_coord + 1;
7689 tgen_ensure(width >= 4,
7690 "geometry: random_orthogonal_polygon: coordinate range too "
7691 "small");
7692
7693 long long min_side = std::max<long long>(3, std::sqrt(n));
7694 if (n > 1000)
7695 min_side = std::max<long long>(min_side, (n + 3) / 4);
7696 tgen_ensure(min_side < width,
7697 "geometry: random_orthogonal_polygon: coordinate range too "
7698 "small");
7699
7700 for (int attempt = 0; attempt < 8; ++attempt) {
7701 std::vector<point<long long>> poly =
7702 detail::build_orthogonal_polygon(n, strict);
7703
7704 if (!strict and poly.size() != static_cast<size_t>(n))
7705 continue;
7706
7707 detail::i128 min_x = poly[0].x(), max_x = poly[0].x();
7708 detail::i128 min_y = poly[0].y(), max_y = poly[0].y();
7709 for (point<long long> p : poly) {
7710 min_x = std::min(min_x, detail::i128(p.x()));
7711 max_x = std::max(max_x, detail::i128(p.x()));
7712 min_y = std::min(min_y, detail::i128(p.y()));
7713 max_y = std::max(max_y, detail::i128(p.y()));
7714 }
7715 if (max_x - min_x >= width or max_y - min_y >= width)
7716 continue;
7717
7718 detail::place_inside_box(poly, min_coord, max_coord);
7719 detail::randomize_cyclic_shift(poly);
7720 return poly;
7721 }
7722
7723 throw tgen::detail::error(
7724 "geometry: random_orthogonal_polygon: generation failed");
7725}
7726
7727} // namespace geometry
7728
7729/************
7730 * *
7731 * HACK *
7732 * *
7733 ************/
7734
7735namespace hack {
7736
7737namespace detail {
7738
7739using namespace tgen::detail;
7740
7741// Computes polynomial hash of a string.
7742// O(|s|).
7743inline int hash_string(const std::string &s, int base, int mod) {
7744 long long h = 0;
7745 for (char c : s)
7746 h = (h * base + c - 'a' + 1) % mod;
7747 return h;
7748}
7749
7750// Estimates the length of the string to very likely have a collision.
7751inline int estimate_length(int alphabet_size, int mod) {
7752 // Magic constants.
7753 double base_len = 2.5 * std::log(std::sqrt(mod));
7754 double scale = std::log(alphabet_size) / std::log(2.0);
7755 double adjusted = base_len / std::max(1.0, scale * 0.7);
7756
7757 return static_cast<int>(std::ceil(adjusted));
7758}
7759
7760// Collides two strings to have the same polynomial hash.
7761// O(sqrt(mod) log(mod)) with high probability.
7762inline std::pair<std::string, std::string>
7763birthday_attack(const std::vector<std::string> &alphabet, int base, int mod) {
7764 tgen_ensure(0 < base and base < mod,
7765 "birthday_attack: base must be in (0, mod)");
7766 std::map<uint64_t, std::vector<int>> seen;
7767 int length = estimate_length(alphabet.size(), mod);
7768
7769 while (true) {
7770 std::vector<int> seq(length);
7771
7772 std::string s;
7773
7774 for (int i = 0; i < length; ++i) {
7775 seq[i] = next<int>(0, alphabet.size() - 1);
7776 s += alphabet[seq[i]];
7777 }
7778
7779 int h = hash_string(s, base, mod);
7780
7781 auto it = seen.find(h);
7782 if (it != seen.end() and it->second != seq) {
7783 std::string a, b;
7784
7785 for (int x : it->second)
7786 a += alphabet[x];
7787 for (int x : seq)
7788 b += alphabet[x];
7789
7790 if (a != b)
7791 return {a, b};
7792 }
7793
7794 seen[h] = seq;
7795 }
7796}
7797
7798// Tried to find correct multipliers for unordered_map/set to force
7799// collisions. O(1).
7800inline std::set<long long> std_hash_multipliers() {
7801 std::set<long long> multipliers = {85229};
7802
7803 // Codeforces GCC GNU G++17 7.3.0 case.
7804 bool codeforces_gcc_case = true;
7805 if (cpp.version_ != 0 and cpp.version_ != 17)
7806 codeforces_gcc_case = false;
7807 if (compiler.kind_ != compiler_kind::unknown and
7808 compiler.kind_ != compiler_kind::gcc)
7809 codeforces_gcc_case = false;
7810 if (compiler.major_ > 7)
7811 codeforces_gcc_case = false;
7812
7813 if (codeforces_gcc_case)
7814 multipliers.insert(107897);
7815
7816 return multipliers;
7817}
7818
7819} // namespace detail
7820
7821// Fetches prefix of length n of the string "abacabadabacabae...".
7822// O(n).
7823inline std::string abacaba(int n) {
7824 tgen_ensure(n > 0, "str: size must be positive");
7825 std::string str = "a";
7826 char c = 'a';
7827 while (static_cast<int>(str.size()) < n) {
7828 int prev_size = str.size();
7829 str += ++c;
7830 for (int j = 0; j < prev_size and static_cast<int>(str.size()) < n; ++j)
7831 str += str[j];
7832 }
7833 return str;
7834}
7835
7836// Two strings that have same polynomial hash for any base, for
7837// mod = power of 2 up to 2^64.
7838// Thue–Morse.
7839// O(1).
7840inline std::pair<std::string, std::string> unsigned_polynomial_hash() {
7841 std::string a, b;
7842 int size = 1 << 10;
7843 for (int i = 0; i < size; ++i) {
7844 a += 'a' + math::detail::popcount(i) % 2;
7845 b += 'a' + ('b' - a[i]);
7846 }
7847 return {a, b};
7848}
7849
7850// Collides two strings to have the same polynomial hash.
7851// O(sqrt(mod) log(mod)) with high probability.
7852// 0 < base < mod.
7853inline std::pair<std::string, std::string> polynomial_hash(int alphabet_size,
7854 int base, int mod) {
7855 tgen_ensure(alphabet_size > 1,
7856 "hack: polynomial_hash: alphabet size must be greater "
7857 "than 1");
7858 tgen_ensure(0 < base and base < mod,
7859 "hack: polynomial_hash: base must be in (0, mod)");
7860
7861 std::vector<std::string> alphabet(alphabet_size);
7862 for (int i = 0; i < alphabet_size; ++i)
7863 alphabet[i] = std::string(1, 'a' + i);
7864 std::iota(alphabet.begin(), alphabet.end(), 'a');
7865 return detail::birthday_attack(alphabet, base, mod);
7866}
7867
7868// Collides two strings to have the same polynomial hash for multiple bases
7869// and mods (up to 2 pairs).
7870// O(sqrt(mod) log^2 (mod)) with high probability,
7871// with mod = max(mod_1, mod_2).
7872inline std::pair<std::string, std::string>
7873polynomial_hash(int alphabet_size, std::vector<int> bases,
7874 std::vector<int> mods) {
7875 tgen_ensure(bases.size() == mods.size(),
7876 "hack: polynomial_hash: bases and mods must have the same "
7877 "size");
7878 tgen_ensure(bases.size() > 0,
7879 "hack: polynomial_hash: must have at least one (base, mod) "
7880 "pair");
7881 tgen_ensure(bases.size() <= 2,
7882 "hack: polynomial_hash: multi-hash hack only supported "
7883 "for up to 2 (base, mod) pairs");
7884
7885 std::vector<std::string> alphabet(alphabet_size);
7886 for (int i = 0; i < alphabet_size; ++i)
7887 alphabet[i] = std::string(1, 'a' + i);
7888 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);
7889 if (bases.size() == 1)
7890 return {S1, T1};
7891 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);
7892}
7893
7894// Returns a list of integers for unordered_map/set to force collisions.
7895// O(size).
7896inline std::vector<long long> std_unordered(int size) {
7897 tgen_ensure(size > 0, "hack: std_unordered: size must be positive");
7898 std::set<long long> multipliers = detail::std_hash_multipliers();
7899 long long mult = 1;
7900 std::set<long long>::iterator it = multipliers.begin();
7901
7902 std::vector<long long> list;
7903 while (static_cast<int>(list.size()) < size) {
7904 list.push_back(mult * (*it));
7905 ++it;
7906 if (it == multipliers.end()) {
7907 it = multipliers.begin();
7908 ++mult;
7909 }
7910 }
7911 return list;
7912}
7913
7914// Returns queries that force \Theta(q sqrt n) asymptotic
7915// for Mo algorithm for offline range queries.
7916// Forces \Theta(q sqrt n) pointer moves for any ordering.
7917// O(n log n + q).
7918inline std::vector<std::pair<int, int>> mo_worst_case(int n, int q) {
7919 std::set<std::pair<int, int>> queries;
7920
7921 // Adversarial case.
7922 int sq = std::sqrt(n);
7923 for (int i = 0; i < sq; ++i) {
7924 for (int j = i; j < sq; ++j) {
7925 if (i * sq < n and j * sq < n)
7926 queries.emplace(i * sq, j * sq);
7927 }
7928 }
7929
7930 // Push extra queries.
7931 for (int i = 0; i < n; ++i)
7932 if (queries.size() < size_t(q)) {
7933 queries.emplace(0, i);
7934 queries.emplace(i, i);
7935 queries.emplace(i, n - 1);
7936 }
7937
7938 std::vector<std::pair<int, int>> pool(queries.begin(), queries.end());
7939 while (pool.size() < size_t(q)) {
7940 int l = next(0, n - 1);
7941 pool.emplace_back(l, next(l, n - 1));
7942 }
7943
7944 return choose(shuffled(pool), q);
7945}
7946
7947// Returns list of strings that have a high cost to insert in a std::set.
7948// Forces cost \Theta(size log(size)).
7949// Generates: {b, ab, aab, aaab, ...}.
7950// O(size log(size)).
7952 std::vector<std::string> list;
7953 int k = 0, left = size;
7954 while (left > 0) {
7955 int cur_size = std::min(left, k + 1);
7956 left -= cur_size;
7957
7958 char right_char = cur_size == k + 1 ? 'b' : 'c';
7959 list.push_back(std::string(cur_size - 1, 'a') + right_char);
7960
7961 ++k;
7962 }
7963 return tgen::shuffled(list);
7964}
7965
7966// Graph for Dijkstra implementations that relax with <= instead of <.
7967// Unit-weight layered graph: 0 -> {1,2}, then disjoint
7968// 2x2 gadgets (i,i+1) -> {i+2,i+3} for i = 1,3,5,... Many vertices share the
7969// same dist from 0; with `d + w <= dist[j]` each pop re-relaxes the whole
7970// frontier below it. m = 2(n - 2) edges.
7971// O(n).
7974 n >= 3,
7975 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");
7976
7977 egraph<int>::value g(n, {}, true);
7978 g.edge_weighted();
7979 g.add_edge(0, 1, 1);
7980 g.add_edge(0, 2, 1);
7981 for (int i = 1; i + 2 < n; i += 2) {
7982 g.add_edge(i, i + 2, 1);
7983 if (i + 3 < n)
7984 g.add_edge(i, i + 3, 1);
7985
7986 g.add_edge(i + 1, i + 2, 1);
7987 if (i + 3 < n)
7988 g.add_edge(i + 1, i + 3, 1);
7989 }
7990
7991 return g.shuffle_except({0});
7992}
7993
7994// Graph for Dijkstra implementations that do not skip stale heap entries
7995// (`if (d > dist[i]) continue`).
7996// Hub mid = n/2: star 0 -> 1..mid-1 (weights 1..mid-1), funnel i -> mid
7997// (weights 1,3,5,...), then mid -> mid+1.. (weight 1).
7998// Without a stale-heap check, mid and its in-neighbors are re-popped and
7999// re-relax.
8000// m = n + mid - 3 edges, mid = floor(n/2).
8001// O(n).
8003 tgen_ensure(n >= 4,
8004 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");
8005
8006 int mid = n / 2;
8007 egraph<int>::value g(n, {}, true);
8008 g.edge_weighted();
8009 for (int i = 1; i < mid; ++i)
8010 g.add_edge(0, i, i);
8011 for (int i = 1; i < mid; ++i)
8012 g.add_edge(i, mid, 2 * (mid - i) - 1);
8013 for (int i = mid + 1; i < n; ++i)
8014 g.add_edge(mid, i, 1);
8015
8016 return g.shuffle_except({0});
8017}
8018
8019// Worst-case for FIFO-SPFA.
8020// Forces Omega(n^2) from vertex 0 (Theta(n*m), m = 2n - 3).
8021// Upper chain ai -> a(i+1) weight 1; lower chain bi -> b(i+1) weight 0;
8022// vertical ai -> bi weight 0; cross bi -> a(i+1) weight 1. Upper chain sets
8023// loose dist first; cross edges from settled bi then improve a(i+1).
8024// m = 2n - 3.
8025// O(n).
8026inline egraph<int>::value spfa(int n) {
8027 tgen_ensure(n >= 2, "hack: spfa: n must be at least 2");
8028 tgen_ensure(n % 2 == 0, "hack: spfa: n must be even");
8029
8030 egraph<int>::value g(n, {}, true);
8031 g.edge_weighted();
8032
8033 const int k = n / 2;
8034 for (int i = 0; i + 1 < k; ++i)
8035 g.add_edge(i, i + 1, 1);
8036 for (int i = 0; i + 1 < k; ++i)
8037 g.add_edge(k + i, k + i + 1, 0);
8038 for (int i = 0; i < k; ++i)
8039 g.add_edge(i, k + i, 0);
8040 for (int i = 0; i + 1 < k; ++i)
8041 g.add_edge(k + i, i + 1, 1);
8042
8043 return g.shuffle_except({0});
8044}
8045
8046// Zadeh (1972) anti-shortest-paths flow network for Edmonds-Karp and Dinitz.
8047// Source is vertex 0; sink is vertex 4l + 2k + 1.
8048// n = 4l + 2k + 2, m = 6l + 4k + k^2 - 4.
8049// O(l + k^2).
8050inline egraph<int>::value dinitz_worst_case(int k, int l) {
8051 tgen_ensure(k >= 1, "hack: dinitz_worst_case: k must be at least 1");
8052 tgen_ensure(l >= 1, "hack: dinitz_worst_case: l must be at least 1");
8053
8054 const int p1 = 2 * l - 1;
8055 const int p2 = 2 * l;
8056 const int q1 = 2 * l + 1;
8057 const int q2 = 2 * l + 2;
8058 const int n = 4 * l + 2 * k + 2;
8059
8060 const int flow_cap = k * k * l;
8061 const int layer_cap = k * k;
8062
8063 auto a = [&](int i) { return 2 * l + 3 + 2 * i; };
8064 auto b = [&](int i) { return 2 * l + 4 + 2 * i; };
8065 auto t = [&](int i) { return 4 * l + 2 * k + 1 - i; };
8066
8067 egraph<int>::value g(n, {}, true);
8068 g.edge_weighted();
8069
8070 for (int i = 0; i + 1 < 2 * l - 1; ++i)
8071 g.add_edge(i, i + 1, flow_cap);
8072 for (int i = 0; i + 1 < 2 * l - 1; ++i)
8073 g.add_edge(t(i + 1), t(i), flow_cap);
8074
8075 for (int i = 0; i < 2 * l - 1; i += 2) {
8076 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);
8077 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);
8078 }
8079
8080 for (int i = 0; i < k; ++i) {
8081 g.add_edge(p1, a(i), flow_cap);
8082 g.add_edge(p2, b(i), flow_cap);
8083 g.add_edge(a(i), q2, flow_cap);
8084 g.add_edge(b(i), q1, flow_cap);
8085 }
8086
8087 for (int i = 0; i < k; ++i)
8088 for (int j = 0; j < k; ++j)
8089 g.add_edge(a(i), b(j), 1);
8090
8091 return g;
8092}
8093
8094// Returns a mask of length 19938, with weights such that xor-ing with mt19937
8095// outputs yields 0.
8096// O(1).
8097template <typename T> std::vector<bool> mt19937_xor_hash() {
8098 static_assert(std::is_same_v<T, int> or std::is_same_v<T, long long>,
8099 "hack: mt19937_xor_hash: T must be int or long long");
8100
8101 constexpr std::size_t deg = 19937;
8102
8103 std::bitset<deg + 1> a, b, c;
8104 b[deg] = c[deg] = 1;
8105 std::size_t l = 0, shift = 1;
8106 std::mt19937 rng32;
8107 std::mt19937_64 rng64;
8108 for (std::size_t n = 0; n < deg * 2; ++n) {
8109 a >>= 1;
8110 if constexpr (std::is_same_v<T, int>)
8111 a[deg] = rng32() & 1;
8112 else
8113 a[deg] = rng64() & 1;
8114
8115 if ((c & a).count() % 2 == 0) {
8116 ++shift;
8117 continue;
8118 }
8119
8120 std::bitset<deg + 1> oc = c;
8121 c ^= (b >> shift);
8122 if (2 * l <= n) {
8123 l = n + 1 - l;
8124 b = oc;
8125 shift = 1;
8126 } else {
8127 ++shift;
8128 }
8129 }
8130
8131 std::vector<bool> mask(deg + 1);
8132 for (std::size_t i = 0; i <= deg; ++i)
8133 mask[i] = c[i];
8134 return mask;
8135}
8136
8137// Convex polygon that breaks naive rotating calipers for maximum vertex
8138// distance (advances j while dist(i, next(j)) > dist(i, j) instead of using
8139// ccw).
8140// O(1).
8141inline std::vector<geometry::point<double>>
8143 return {
8144 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},
8145 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},
8146 };
8147}
8148
8149namespace detail {
8150
8151// Builds a hack block of order k (length fib(2k+1)).
8152// O(fib(2k+1)).
8153inline std::vector<int> segment_tree_beats_worst_case_block(int k) {
8154 tgen_ensure(k >= 1,
8155 "hack: segment_tree_beats_worst_case: k must be at least 1");
8156
8157 std::vector<int> a(k + 1), b(k + 1);
8158 std::vector<std::vector<int>> vf(k + 1), vg(k + 1);
8159
8160 a[1] = b[1] = 1;
8161 vf[1] = {1};
8162 vg[1] = {1, 0};
8163
8164 for (int i = 2; i <= k; ++i) {
8165 b[i] = b[i - 1] + a[i - 1];
8166 a[i] = b[i] + a[i - 1];
8167 for (int x : vf[i - 1])
8168 vf[i].push_back(x + a[i] + b[i]);
8169 vf[i].push_back(a[i]);
8170 for (int x : vg[i - 1])
8171 vf[i].push_back(x + a[i]);
8172 vg[i] = vf[i];
8173 vg[i].push_back(0);
8174 for (int x : vg[i - 1])
8175 vg[i].push_back(x);
8176 }
8177
8178 vf[k].push_back(0);
8179 return vf[k];
8180}
8181
8182// Appends one update round for the tiled array (offset (round * an) mod L).
8183// O(fib(2k+1)).
8184inline void
8185segment_tree_beats_append_round(std::vector<std::vector<int>> &updates,
8186 int block_len, int an, int bn, int n,
8187 int round) {
8188 const int off = (round * an) % block_len;
8189 const int add_off = (off + block_len - bn) % block_len;
8190 for (int k = 0; k < block_len; ++k) {
8191 const int s = k * block_len * block_len;
8192 const int sub_end = off + an;
8193 if (sub_end <= block_len)
8194 updates.push_back({1, s + off, s + sub_end, bn});
8195 else {
8196 updates.push_back({1, s + off, s + block_len, bn});
8197 updates.push_back({1, s, s + (sub_end - block_len), bn});
8198 }
8199 const int add_end = add_off + bn;
8200 if (add_end <= block_len)
8201 updates.push_back({0, s + add_off, s + add_end, an});
8202 else {
8203 updates.push_back({0, s + add_off, s + block_len, an});
8204 updates.push_back({0, s, s + (add_end - block_len), an});
8205 }
8206 }
8207 updates.push_back({2, 0, n, an});
8208 for (int k = 0; k < block_len; ++k) {
8209 const int s = k * block_len * block_len;
8210 updates.push_back({3, s + (off + an - 1) % block_len, 0});
8211 }
8212}
8213
8214} // namespace detail
8215
8216// Array and updates for worst case of segment tree beats.
8217// O(fib(2k+1)^3 + q).
8218inline std::pair<std::vector<int>, std::vector<std::vector<int>>>
8219segment_tree_beats_worst_case(int k, int q) {
8220 tgen_ensure(k >= 1,
8221 "hack: segment_tree_beats_worst_case: k must be at least 1");
8222 tgen_ensure(k <= 7, "hack: segment_tree_beats_worst_case: k too large");
8223 tgen_ensure(q > 0,
8224 "hack: segment_tree_beats_worst_case: q must be positive");
8225
8226 const auto &fib = math::fibonacci();
8227 const int block_len = fib[k * 2 + 1];
8228 const int an = fib[k * 2];
8229 const int bn = fib[k * 2 - 1];
8230
8231 const int len = block_len;
8232 const int total = len * len * len;
8233
8234 std::vector<int> block = detail::segment_tree_beats_worst_case_block(k);
8235 std::vector<int> arr(total, 0);
8236 for (int x = 0; x < block_len; ++x) {
8237 const int s = x * len * len;
8238 for (int i = 0; i < block_len; ++i)
8239 arr[s + i] = block[i];
8240 }
8241
8242 std::vector<std::vector<int>> updates;
8243 updates.reserve(q);
8244 const int n = total;
8245 for (int round = 0; updates.size() < static_cast<std::size_t>(q); ++round) {
8246 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,
8247 round);
8248 if (updates.size() > static_cast<std::size_t>(q))
8249 updates.resize(q);
8250 }
8251 return {arr, updates};
8252}
8253
8254namespace detail {
8255
8256// Near-balanced binary tree in heap layout: parent i, children 2i+1 and 2i+2.
8257// Height Theta(log n).
8258// O(n).
8259inline tree::value binary_heap_tree(int n) {
8260 std::vector<std::pair<int, int>> edges;
8261 for (int i = 0; i < n; ++i) {
8262 if (2 * i + 1 < n)
8263 edges.emplace_back(i, 2 * i + 1);
8264 if (2 * i + 2 < n)
8265 edges.emplace_back(i, 2 * i + 2);
8266 }
8267 return tree::value(n, edges);
8268}
8269
8270// Appends leaves of the heap subtree rooted at `u` in left-to-right order.
8271// O(subtree size).
8272inline void heap_subtree_leaves(int n, int u, std::vector<int> &out) {
8273 if (2 * u + 1 >= n) {
8274 out.push_back(u);
8275 return;
8276 }
8277 heap_subtree_leaves(n, 2 * u + 1, out);
8278 if (2 * u + 2 < n)
8279 heap_subtree_leaves(n, 2 * u + 2, out);
8280}
8281
8282// Path queries between random leaves in the left and right subtrees of the
8283// root. On correct HLD or centroid decomposition each query visits
8284// Theta(log n) chains / centroid-tree nodes.
8285// O(n + q).
8286inline std::vector<std::pair<int, int>> tree_path_worst_queries(int n, int q) {
8287 std::vector<int> left, right;
8288 if (n > 1)
8289 heap_subtree_leaves(n, 1, left);
8290 if (n > 2)
8291 heap_subtree_leaves(n, 2, right);
8292
8293 std::vector<std::pair<int, int>> queries;
8294 for (int i = 0; i < q; ++i)
8295 queries.emplace_back(pick(left), pick(right));
8296 return queries;
8297}
8298
8299// Reverses the lowest `bits` bits of x.
8300// O(bits).
8301inline int reverse_bits(int x, int bits) {
8302 int r = 0;
8303 for (int i = 0; i < bits; ++i) {
8304 r = (r << 1) | (x & 1);
8305 x >>= 1;
8306 }
8307 return r;
8308}
8309
8310// Wilber bit-reversal leaf tour: maximizes left/right preferred-child
8311// alternations on a balanced tree, forcing Theta(q log n) preferred-path
8312// switches in link-cut trees.
8313// O(n log n + q).
8314inline std::vector<int> lct_worst_access(int n, int q) {
8315 int first_leaf = n / 2;
8316 int m = n - first_leaf;
8317
8318 int bits = 0;
8319 while ((1u << bits) < static_cast<unsigned>(m))
8320 ++bits;
8321
8322 std::vector<int> order;
8323 int span = 1 << bits;
8324 for (int i = 0; i < span; ++i) {
8325 int r = reverse_bits(i, bits);
8326 if (r < m)
8327 order.push_back(first_leaf + r);
8328 }
8329
8330 std::vector<int> access;
8331 for (int i = 0; i < q; ++i)
8332 access.push_back(order[i % m]);
8333 return access;
8334}
8335
8336} // namespace detail
8337
8338// Near-balanced tree plus path queries that force Theta(log n) centroid-tree
8339// nodes per query on correct centroid-decomposition implementations.
8340// O(n + q).
8341inline std::pair<tree::value, std::vector<std::pair<int, int>>>
8342centroid_decomposition_worst_case(int n, int q) {
8344 n >= 3,
8345 "hack: centroid_decomposition_worst_case: n must be at least 3");
8347 q >= 1,
8348 "hack: centroid_decomposition_worst_case: q must be at least 1");
8349
8350 return {detail::binary_heap_tree(n), detail::tree_path_worst_queries(n, q)};
8351}
8352
8353// Near-balanced tree plus path queries that force Theta(log n) heavy-light
8354// chains per query on correct heavy-light decomposition implementations.
8355// O(n + q).
8356inline std::pair<tree::value, std::vector<std::pair<int, int>>>
8357heavy_light_decomposition_worst_case(int n, int q) {
8359 n >= 3,
8360 "hack: heavy_light_decomposition_worst_case: n must be at least "
8361 "3");
8363 q >= 1,
8364 "hack: heavy_light_decomposition_worst_case: q must be at least 1");
8365
8366 return {detail::binary_heap_tree(n), detail::tree_path_worst_queries(n, q)};
8367}
8368
8369// Near-balanced tree plus a Wilber bit-reversal leaf-access sequence.
8370// O(n log n + q).
8371inline std::pair<tree::value, std::vector<int>>
8372link_cut_tree_worst_case(int n, int q) {
8373 tgen_ensure(n >= 2, "hack: link_cut_tree_worst_case: n must be at least 2");
8374 tgen_ensure(q >= 1, "hack: link_cut_tree_worst_case: q must be at least 1");
8375
8376 return {detail::binary_heap_tree(n), detail::lct_worst_access(n, q)};
8377}
8378
8379} // namespace hack
8380
8381/*********************
8382 * *
8383 * MISCELLANEOUS *
8384 * *
8385 *********************/
8386
8387namespace misc {
8388
8389// Generates a uniformly random balanced parentheses sequence with k '(' and k
8390// ')'. Valid means that for no prefix there are more ')' than '('.
8391// O(size).
8392inline std::string gen_parenthesis(int size) {
8393 tgen_ensure(size > 0 and size % 2 == 0,
8394 "misc: parenthesis: size must be a positive even number");
8395
8396 int k = size / 2;
8397 std::string s;
8398 int open = 0, close = 0;
8399
8400 for (int i = 0; i < size; ++i) {
8401 if (open == k) {
8402 s += ')';
8403 ++close;
8404 continue;
8405 }
8406 if (open == close) {
8407 s += '(';
8408 ++open;
8409 continue;
8410 }
8411
8412 long long a = k - open, b = k - close, h = open - close;
8413
8414 // Probability of placing '(':
8415 // P('(') = (k - open) * (h + 2) / ((k - open + k - close) * (h + 1))
8416 // Derived from ballot numbers ratio.
8417 long long num = a * (h + 2);
8418 long long den = (a + b) * (h + 1);
8419
8420 if (next<long long>(1, den) <= num) {
8421 s += '(';
8422 ++open;
8423 } else {
8424 s += ')';
8425 ++close;
8426 }
8427 }
8428
8429 return s;
8430}
8431
8432} // namespace misc
8433
8434} // 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:7023
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:6558
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:6956
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:7655
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:7677
wgraph< VWeight, int > vgraph
Vertex-weighted labeled graphs.
Definition tgen.h:6411
graph::value C(int n, bool is_directed=false)
Cycle graph.
Definition tgen.h:6442
wgraph< int, EWeight > egraph
Edge-weighted labeled graphs.
Definition tgen.h:6414
graph::value S(int n)
Star undirected graph.
Definition tgen.h:6466
graph::value K(int n1, int n2)
Complete bipartite undirected graph.
Definition tgen.h:6455
graph::value K(int n)
Complete undirected graph.
Definition tgen.h:6425
wgraph< int, int > graph
Unweighted labeled graphs.
Definition tgen.h:6417
graph::value P(int n, bool is_directed=false)
Path graph.
Definition tgen.h:6431
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:7918
std::vector< bool > mt19937_xor_hash()
Mask that forces a zero XOR hash from std::mt19937 or std::mt19937_64.
Definition tgen.h:8097
egraph< int >::value spfa(int n)
Worst-case for FIFO-SPFA.
Definition tgen.h:8026
egraph< int >::value non_strict_relaxation_dijkstra_bug(int n)
Directed weighted graph for Dijkstra with non-strict relaxation.
Definition tgen.h:7972
std::string abacaba(int n)
Returns the prefix of the infinite word "abacabad...".
Definition tgen.h:7823
std::vector< geometry::point< double > > naive_rotating_calipers_max_dist_bug()
Convex polygon that breaks naive rotating calipers for maximum distance.
Definition tgen.h:8142
std::vector< long long > std_unordered(int size)
List of integers that tries to force collision on std::unordered_set.
Definition tgen.h:7896
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:7951
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:7840
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:7853
egraph< int >::value dinitz_worst_case(int k, int l)
Flow network for Edmonds-Karp and Dinitz worst-case.
Definition tgen.h:8050
egraph< int >::value stale_heap_dijkstra_bug(int n)
Directed weighted graph for Dijkstra without a stale-heap check.
Definition tgen.h:8002
uint64_t prime_from(uint64_t left)
Computes smallest prime from given value.
Definition tgen.h:2906
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:2935
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:3183
uint64_t totient(uint64_t n)
Euler's totient function.
Definition tgen.h:2766
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:3004
uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod)
Computes largest congruent up to given value.
Definition tgen.h:3092
uint64_t gen_prime(uint64_t left, uint64_t right)
Generates a random prime in given range.
Definition tgen.h:2881
std::vector< uint64_t > factor(uint64_t n)
Factors a number into primes.
Definition tgen.h:2735
int num_divisors(uint64_t n)
Computes the number of divisors of a given number.
Definition tgen.h:2925
bool is_prime(uint64_t n)
Checks if a number is prime.
Definition tgen.h:2483
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:3117
constexpr int FFT_MOD
FFT/NTT mod.
Definition tgen.h:3098
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:2994
uint64_t prime_upto(uint64_t right)
Computes largest prime up to given value.
Definition tgen.h:2915
uint64_t highly_composite_upto(uint64_t right)
Largest highly composite number up to given number.
Definition tgen.h:2871
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:3052
std::vector< std::pair< uint64_t, int > > factor_by_prime(uint64_t n)
Factors a number into primes and its powers.
Definition tgen.h:2745
const std::vector< uint64_t > & fibonacci()
Fetches Fibonacci numbers.
Definition tgen.h:3101
uint64_t modular_inverse(uint64_t a, uint64_t mod)
Computes modular inverse.
Definition tgen.h:2760
uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod)
Computes smallest congruent from given value.
Definition tgen.h:3043
const std::vector< uint64_t > & highly_composites()
Fetches highly composite numbers.
Definition tgen.h:2831
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:3372
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:3281
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:2950
std::pair< uint64_t, uint64_t > prime_gap_upto(uint64_t right)
Largest prime gap up to given number.
Definition tgen.h:2812
std::string gen_parenthesis(int size)
Generates a random valid parenthesis sequence.
Definition tgen.h:8392
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:5018
wtree< int, EWeight > etree
Edge-weighted labeled trees.
Definition tgen.h:5021
wtree< int, int > tree
Unweighted labeled trees.
Definition tgen.h:5024
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:6477
T x() const
x coordinate.
Definition tgen.h:6494
bool operator==(const point &p) const
Coordinate-wise equality.
Definition tgen.h:6517
product_t operator*(const point &p) const
Dot product.
Definition tgen.h:6535
product_t operator^(const point &p) const
Cross product.
Definition tgen.h:6542
point operator*(T c) const
Scalar multiplication.
Definition tgen.h:6532
point operator-(const point &p) const
Vector subtraction.
Definition tgen.h:6527
point(T x=0, T y=0)
Constructs a point.
Definition tgen.h:6491
T y() const
y coordinate.
Definition tgen.h:6497
bool operator<(const point &p) const
Lexicographic order.
Definition tgen.h:6510
point operator+(const point &p) const
Vector addition.
Definition tgen.h:6522
List value.
Definition tgen.h:1683
int size() const
Returns the size of the list value.
Definition tgen.h:1696
value(const std::vector< T > &vec)
Creates a list value from a std::vector.
Definition tgen.h:1692
value & sort()
Sorts the list in non-decreasing order.
Definition tgen.h:1712
auto to_std() const
Converts the list to a std::vector.
Definition tgen.h:1794
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:1726
value choose(int k) const
Chooses a uniformly random subsequence of given length.
Definition tgen.h:1768
value operator+(const value &rhs) const
Concatenates two lists.
Definition tgen.h:1733
T & operator[](int idx)
Accesses the element at some position of the list.
Definition tgen.h:1699
value & reverse()
Reverses the list.
Definition tgen.h:1719
T pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the list with given probabilities.
Definition tgen.h:1755
value & shuffle()
Shuffles the list in place.
Definition tgen.h:1742
T pick() const
Returns a uniformly random element.
Definition tgen.h:1750
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 & adjacent_different()
Restricts generator s.t. adjacent values are different.
Definition tgen.h:1675
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:1809
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:4223
T second() const
Returns the second element of a pair value.
Definition tgen.h:4235
value(const T &first, const T &second)
Creates a pair value from first and second values.
Definition tgen.h:4231
value(const std::pair< T, T > &pair)
Creates a pair value from a std::pair.
Definition tgen.h:4230
auto to_std() const
Converts the pair to a std::pair.
Definition tgen.h:4249
T first() const
Returns the first element of a pair value.
Definition tgen.h:4234
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:4238
Pair generator.
Definition tgen.h:4166
value gen() const
Generates a uniformly random value from the set of valid pairs.
Definition tgen.h:4262
pair & neq()
Restricts generator s.t. first is not equal to second.
Definition tgen.h:4193
pair & leq()
Restricts generator s.t. first is less than or equal to second.
Definition tgen.h:4211
pair & lt()
Restricts generator s.t. first is less than second.
Definition tgen.h:4199
pair & gt()
Restricts generator s.t. first is greater than second.
Definition tgen.h:4205
pair(T both_left, T both_right)
Creates pair generator defined by range of values for both first and second.
Definition tgen.h:4183
pair & eq()
Restricts generator s.t. first is equal to second.
Definition tgen.h:4187
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:4174
pair & geq()
Restricts generator s.t. first is greater than or equal to second.
Definition tgen.h:4217
Permutation value.
Definition tgen.h:2236
value & print_1_based()
Sets that printed values are 1-based.
Definition tgen.h:2322
std::vector< int > to_std() const
Converts the permutation to a std::vector.
Definition tgen.h:2365
const int & operator[](int idx) const
Returns the image at some position of the permutation.
Definition tgen.h:2265
std::vector< int > to_std_1_based() const
Converts the permutation to a 1-based std::vector.
Definition tgen.h:2369
value & sort()
Sorts the permutation in non-decreasing order.
Definition tgen.h:2289
int parity() const
Parity of the permutation.
Definition tgen.h:2273
int pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the permutation with given probabilities.
Definition tgen.h:2342
int pick() const
Returns a uniformly random element.
Definition tgen.h:2337
value & reverse()
Reverses the permutation.
Definition tgen.h:2297
value(const std::vector< int > &vec)
Creates a permutation value from a std::vector.
Definition tgen.h:2244
int size() const
Returns the size of the permutation value.
Definition tgen.h:2262
value & shuffle()
Shuffles the permutation.
Definition tgen.h:2329
value & inverse()
Inverse of the permutation.
Definition tgen.h:2304
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:2314
Permutation generator.
Definition tgen.h:2204
value gen() const
Generates a uniformly random value from the set of valid permutations.
Definition tgen.h:2379
permutation & cycles(const std::vector< int > &cycle_sizes)
Restricts generator s.t. cycle sizes are fixed.
Definition tgen.h:2223
permutation(int size)
Creates permutation generator defined by size.
Definition tgen.h:2210
permutation & fix(int idx, int val)
Restricts generator s.t. value at index is fixed.
Definition tgen.h:2215
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:3830
char pick() const
Returns a uniformly random element.
Definition tgen.h:3902
char pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the string with given probabilities.
Definition tgen.h:3907
value choose(int k) const
Chooses a uniformly random subsequence of given length.
Definition tgen.h:3920
value & lowercase()
Sets all characters to lowercase.
Definition tgen.h:3872
value & reverse()
Reverses the string.
Definition tgen.h:3865
int size() const
Returns the size of the string value.
Definition tgen.h:3842
value(const std::string &str)
Creates a string value from a std::string.
Definition tgen.h:3837
value & shuffle()
Shuffles the string.
Definition tgen.h:3894
char & operator[](int idx)
Accesses the character at some position of the string.
Definition tgen.h:3845
value & uppercase()
Sets all characters to uppercase.
Definition tgen.h:3880
value operator+(const value &rhs) const
Concatenates two strings.
Definition tgen.h:3888
std::string to_std() const
Converts the string to a std::string.
Definition tgen.h:3941
value & sort()
Sorts the characters in non-decreasing order.
Definition tgen.h:3858
String generator.
Definition tgen.h:3715
str & different(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are different.
Definition tgen.h:3802
str & palindrome(int left, int right)
Restricts generator s.t. range is a palindrome.
Definition tgen.h:3778
value gen() const
Generates a uniformly random value from the set of valid strings.
Definition tgen.h:3947
str(int size, char value_left='a', char value_right='z')
Creates string generator defined by size and range of characters.
Definition tgen.h:3722
str & different(std::set< int > indices)
Restricts generator s.t. all characters in index set are different.
Definition tgen.h:3795
str(const std::string &regex, Args &&...args)
Creates string generator defined by regex.
Definition tgen.h:3735
str & equal(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are equal.
Definition tgen.h:3757
str & equal(std::set< int > indices)
Restricts generator s.t. all characters in index set are equal.
Definition tgen.h:3750
str & equal_range(int left, int right)
Restricts generator s.t. all characters at index range are equal.
Definition tgen.h:3764
str & fix(int idx, char character)
Restricts generator s.t. character at index is fixed.
Definition tgen.h:3743
str & all_equal()
Restricts generator s.t. all values are equal.
Definition tgen.h:3771
str & different_range(int left, int right)
Restricts generator s.t. all characters at index range are different.
Definition tgen.h:3809
str & palindrome()
Restricts generator s.t. string is a palindrome.
Definition tgen.h:3788
str & all_different()
Restricts generator s.t. all characters are different.
Definition tgen.h:3816
str(int size, std::set< char > chars)
Creates string generator defined by character set.
Definition tgen.h:3729
str & adjacent_different()
Restricts generator s.t. adjacent values are different.
Definition tgen.h:3823
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:5200
value & print_nm()
Prints number of vertices and edges before edge list.
Definition tgen.h:5377
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
Definition tgen.h:5319
value operator!() const
Graph complement of unweighted graph.
Definition tgen.h:5752
std::tuple< int, int, std::vector< std::set< int > > > to_std() const
Converts the graph to std types.
Definition tgen.h:5843
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
Definition tgen.h:5387
int n() const
Number of vertices.
Definition tgen.h:5301
value operator+(const value &rhs) const
Concatenates two graphs (disjoint union).
Definition tgen.h:5786
value & disjoint_union(const value &rhs)
Disjoint union with another graph.
Definition tgen.h:5623
int m() const
Number of edges.
Definition tgen.h:5304
std::tuple< int, int, std::vector< std::set< int > > > to_std_1_based() const
Converts the graph to 1-based std types.
Definition tgen.h:5851
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another graph at given vertex pairs.
Definition tgen.h:5546
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
Definition tgen.h:5324
value(const std::vector< std::set< int > > &adj, bool is_directed=false)
Builds a graph from an adjacency list.
Definition tgen.h:5219
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:5240
wgraph< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
Definition tgen.h:5331
const std::vector< std::set< int > > & adj() const
Adjacency list.
Definition tgen.h:5310
value & add_vertices(int k, std::optional< std::vector< VWeight > > new_vertex_weights=std::nullopt)
Adds new isolated vertices.
Definition tgen.h:5458
value & print_1_based()
Sets that printed vertex ids are 1-based.
Definition tgen.h:5370
value & random_connected_subgraph(int num_edges)
Random subgraph with a fixed number of edges that keeps components connected.
Definition tgen.h:5662
value(const typename wtree< VWeight, EWeight >::value &t)
Builds an undirected graph from a tree.
Definition tgen.h:5271
value & random_subgraph(int num_edges)
Random subgraph with a fixed number of edges.
Definition tgen.h:5629
value & edge_weighted()
Enables edge-weighted mode on an edgeless graph.
Definition tgen.h:5356
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:5519
bool is_directed() const
If the graph is directed.
Definition tgen.h:5307
value & add_edge(int u, int v, std::optional< EWeight > w=std::nullopt)
Adds an edge between two vertices.
Definition tgen.h:5485
value & shuffle()
Shuffles all vertices and edge order.
Definition tgen.h:5453
wgraph< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Definition tgen.h:5345
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Definition tgen.h:5316
Labeled weighted graph generator.
Definition tgen.h:5164
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:5174
static value gen_bipartite(int n1, int n2, int m, bool connected=false)
Generates a random bipartite graph.
Definition tgen.h:6202
value get_connected() const
Random connected undirected graph extending preset edges.
Definition tgen.h:5922
static value gen_np(int n, double p, bool is_directed=false, bool has_self_loops=false)
Generates a random graph where each edge is included independently.
Definition tgen.h:6268
value gen() const
Generates a uniformly random graph satisfying the constraints.
Definition tgen.h:5898
wgraph & add_edge(int u, int v)
Adds a preset edge that must appear in the generated graph.
Definition tgen.h:5182
value get_acyclic() const
Random directed acyclic graph extending preset edges.
Definition tgen.h:5996
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:6099
wgraph & add_edges_from(const value &rhs)
Adds all edges from another graph as preset edges.
Definition tgen.h:5885
Labeled tree value.
Definition tgen.h:4412
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another tree at given vertex pairs.
Definition tgen.h:4716
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Definition tgen.h:4499
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:4449
value(const typename wgraph< VWeight, EWeight >::value &g)
Builds a tree from a graph via a Kruskal-like random spanning tree.
Definition tgen.h:6361
value & print_parents(int root=-1)
Prints in parent format instead of edge list.
Definition tgen.h:4570
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
Definition tgen.h:4502
value & edge_weighted()
Enables edge-weighted mode on an edgeless tree.
Definition tgen.h:4540
int n() const
Returns the number of vertices.
Definition tgen.h:4493
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
Definition tgen.h:4582
const std::vector< std::set< int > > & adj() const
Adjacency list.
Definition tgen.h:4496
value(const std::vector< std::set< int > > &adj)
Builds a tree from an adjacency list.
Definition tgen.h:4429
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
Definition tgen.h:4507
value & shuffle()
Shuffles vertices and edge order.
Definition tgen.h:4651
std::pair< int, std::vector< std::set< int > > > to_std() const
Converts the tree to a std types.
Definition tgen.h:4879
wtree< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
Definition tgen.h:4514
value & print_n()
Prints the number of vertices before the tree.
Definition tgen.h:4561
std::pair< int, std::vector< std::set< int > > > to_std_1_based() const
Converts the tree to 1-based std types.
Definition tgen.h:4885
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:4689
value & print_1_based()
Sets that printed vertex ids are 1-based.
Definition tgen.h:4554
wtree< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Definition tgen.h:4528
Labeled weighted tree generator.
Definition tgen.h:4385
wtree & add_edge(int u, int v)
Restricts generator s.t. some edge is present.
Definition tgen.h:4397
static value gen_skewed(int n, int elongation)
Random skewed tree (large diameter).
Definition tgen.h:4983
value gen() const
Generates a uniformly random value from the set of valid trees.
Definition tgen.h:4926
wtree(int n)
Creates a tree generator with specified number of vertices.
Definition tgen.h:4391
static value gen_kruskal(int n)
Kruskal-like random labeled tree.
Definition tgen.h:4993