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