1#pragma once23#include "common.h"4#include "hash.h"5#include "printers.h"6#include "random.h"7#include "sequence_ops.h"89#include <algorithm>10#include <initializer_list>11#include <numeric>12#include <set>13#include <string>14#include <type_traits>15#include <unordered_set>16#include <unordered_map>17#include <utility>18#include <vector>1920namespace jngen {2122template<typename T>23class GenericArray : public ReprProxy<GenericArray<T>>, public std::vector<T> {24public:25 typedef std::vector<T> Base;2627 using Base::Base;2829 GenericArray() {}30 GenericArray(const GenericArray<T>&) = default;31 GenericArray& operator=(const GenericArray<T>&) = default;32 GenericArray(GenericArray<T>&&) = default;33 GenericArray& operator=(GenericArray<T>&&) = default;3435 ~GenericArray() {}3637 /* implicit */ GenericArray(const Base& base) :38 Base(base)39 { }4041 using Base::at;42 using Base::size;43 using Base::resize;44 using Base::begin;45 using Base::end;46 using Base::insert;47 using Base::clear;48 using Base::erase;4950 void extend(size_t requiredSize) {51 checkLargeParameter(requiredSize);52 if (requiredSize > size()) {53 resize(requiredSize);54 }55 }5657 template<typename F, typename ...Args>58 static GenericArray<T> randomf(size_t size, F func, const Args& ... args);59 template<typename F, typename ...Args>60 static GenericArray<T> randomfUnique(61 size_t size, F func, const Args& ... args);62 template<typename F, typename ...Args>63 static GenericArray<T> randomfAll(F func, const Args& ... args);6465 template<typename ...Args>66 static GenericArray<T> random(size_t size, const Args& ... args);67 template<typename ...Args>68 static GenericArray<T> randomUnique(size_t size, const Args& ... args);69 template<typename ...Args>70 static GenericArray<T> randomAll(const Args& ... args);7172 static GenericArray<T> id(size_t size, T start = T{});7374 GenericArray<T>& shuffle();75 GenericArray<T> shuffled() const;7677 GenericArray<T>& reverse();78 GenericArray<T> reversed() const;7980 GenericArray<T>& sort();81 GenericArray<T> sorted() const;8283 template<typename Comp>84 GenericArray<T>& sort(Comp&& comp);85 template<typename Comp>86 GenericArray<T> sorted(Comp&& comp) const;8788 GenericArray<T>& unique();89 GenericArray<T> uniqued() const;9091 GenericArray<T> inverse() const;9293 template<typename Integer>94 GenericArray<T> subseq(const std::vector<Integer>& indices) const;9596 template<typename Integer>97 GenericArray<T> subseq(98 const std::initializer_list<Integer>& indices) const;99100 T choice() const;101 GenericArray<T> choice(size_t count) const;102 GenericArray<T> choiceWithRepetition(size_t count) const;103104 GenericArray<T>& operator+=(const GenericArray<T>& other);105 GenericArray<T> operator+(const GenericArray<T>& other) const;106107 GenericArray<T>& operator*=(int k);108 GenericArray<T> operator*(int k) const;109110 operator std::string() const;111};112113template<typename T>114template<typename ...Args>115GenericArray<T> GenericArray<T>::random(size_t size, const Args& ... args) {116 checkLargeParameter(size);117 GenericArray<T> result(size);118 for (T& x: result) {119 x = rnd.tnext<T>(args...);120 }121 return result;122}123124template<typename T>125template<typename F, typename ...Args>126GenericArray<T> GenericArray<T>::randomf(127 size_t size,128 F func,129 const Args& ... args)130{131 checkLargeParameter(size);132 GenericArray<T> result(size);133 for (T& x: result) {134 x = func(args...);135 }136 return result;137}138139namespace detail {140141template<typename T, typename Enable = std::size_t>142struct DictContainer {143 typedef std::set<T> type;144};145146template<typename T>147struct DictContainer<T, typename std::hash<T>::result_type>148{149 typedef std::unordered_set<T> type;150};151152} // namespace detail153154template<typename T>155template<typename F, typename ...Args>156GenericArray<T> GenericArray<T>::randomfUnique(157 size_t size,158 F func,159 const Args& ... args)160{161 typename detail::DictContainer<T>::type set;162 checkLargeParameter(size);163 GenericArray<T> result;164 result.reserve(size);165166 size_t retries = (size + 10) * log(size + 10) * 2;167168 while (result.size() != size) {169 T t = func(args...);170 if (!set.count(t)) {171 set.insert(t);172 result.push_back(t);173 }174175 if (--retries == 0) {176 ensure(false, "There are not enough unique elements");177 }178179 }180181 return result;182}183184template<typename T>185template<typename ...Args>186GenericArray<T> GenericArray<T>::randomUnique(187 size_t size, const Args& ... args)188{189 return GenericArray<T>::randomfUnique(190 size,191 [](Args... args) { return rnd.tnext<T>(args...); },192 args...);193}194195template<typename T>196template<typename F, typename ...Args>197GenericArray<T> GenericArray<T>::randomfAll(198 F func,199 const Args& ... args)200{201 typename detail::DictContainer<T>::type set;202 GenericArray<T> result;203204 size_t timeAfterLastHit = 0;205206 while (true) {207 T t = func(args...);208 if (!set.count(t)) {209 set.insert(t);210 result.push_back(t);211 timeAfterLastHit = 0;212 }213214 ++timeAfterLastHit;215216 // Probability of finding not all elements is about e^{-20} ~= 1e-9217 if (timeAfterLastHit > (result.size() + 10) * 20) {218 return result;219 }220 }221}222223template<typename T>224template<typename ...Args>225GenericArray<T> GenericArray<T>::randomAll(const Args& ... args)226{227 return GenericArray<T>::randomfAll(228 [](Args... args) { return rnd.tnext<T>(args...); },229 args...);230}231232template<typename T>233GenericArray<T> GenericArray<T>::id(size_t size, T start) {234 constexpr bool enable = std::is_integral<T>::value;235 static_assert(enable, "Cannot call Array<T>::id with non-integral T");236 checkLargeParameter(size);237238 if (enable) {239 GenericArray<T> result(size);240 std::iota(result.begin(), result.end(), start);241 return result;242 } else {243 return {};244 }245}246247template<typename T>248GenericArray<T>& GenericArray<T>::shuffle() {249 jngen::shuffle(begin(), end());250 return *this;251}252253template<typename T>254GenericArray<T> GenericArray<T>::shuffled() const {255 auto res = *this;256 res.shuffle();257 return res;258}259260template<typename T>261GenericArray<T>& GenericArray<T>::reverse() {262 std::reverse(begin(), end());263 return *this;264}265266template<typename T>267GenericArray<T> GenericArray<T>::reversed() const {268 auto res = *this;269 res.reverse();270 return res;271}272273template<typename T>274GenericArray<T>& GenericArray<T>::sort() {275 std::sort(begin(), end());276 return *this;277}278279template<typename T>280GenericArray<T> GenericArray<T>::sorted() const {281 auto res = *this;282 res.sort();283 return res;284}285286template<typename T>287template<typename Comp>288GenericArray<T>& GenericArray<T>::sort(Comp&& comp) {289 std::sort(begin(), end(), comp);290 return *this;291}292293template<typename T>294template<typename Comp>295GenericArray<T> GenericArray<T>::sorted(Comp&& comp) const {296 auto res = *this;297 res.sort(comp);298 return res;299}300301template<typename T>302GenericArray<T>& GenericArray<T>::unique() {303 erase(std::unique(begin(), end()), end());304 return *this;305}306307template<typename T>308GenericArray<T> GenericArray<T>::uniqued() const {309 auto res = *this;310 res.unique();311 return res;312}313314template<typename T>315GenericArray<T> GenericArray<T>::inverse() const {316 static_assert(317 std::is_integral<T>::value,318 "Can only take inverse permutation of integral array");319 int n = size();320321 if (n == 0) {322 return *this;323 }324325 // sanity check326 ensure(*max_element(begin(), end()) == n-1 &&327 *min_element(begin(), end()) == 0,328 "Trying to take inverse of the array which is not a permutation");329330 const static T NONE = static_cast<T>(-1);331 GenericArray<T> result(n, NONE);332 for (int i = 0; i < n; ++i) {333 ensure(result[at(i)] == NONE,334 "Trying to take inverse of the array which is not a permutation");335 result[at(i)] = i;336 }337338 return result;339}340341template<typename T>342template<typename Integer>343GenericArray<T> GenericArray<T>::subseq(344 const std::vector<Integer>& indices) const345{346 GenericArray<T> result;347 result.reserve(indices.size());348 for (Integer idx: indices) {349 result.push_back(at(idx));350 }351 return result;352}353354// TODO(ifsmirnov): ever need to make it faster?355template<typename T>356template<typename Integer>357GenericArray<T> GenericArray<T>::subseq(358 const std::initializer_list<Integer>& indices) const359{360 return subseq(std::vector<T>(indices));361}362363template<typename T>364T GenericArray<T>::choice() const {365 return jngen::choice(begin(), end());366}367368template<typename T>369GenericArray<T> GenericArray<T>::choice(size_t count) const {370 ensure(371 count <= size(),372 "Use Array::choiceWithRepetition to select more than size() elements");373374 size_t n = size();375376 std::unordered_map<size_t, size_t> used;377 std::vector<size_t> res;378 for (size_t i = 0; i < count; ++i) {379 size_t oldValue = used.count(n-i-1) ? used[n-i-1] : n-i-1;380 size_t index = rnd.tnext<size_t>(n-i);381 res.push_back(used.count(index) ? used[index] : index);382 used[index] = oldValue;383 }384385 return subseq(res);386}387388template<typename T>389GenericArray<T> GenericArray<T>::choiceWithRepetition(size_t count) const {390 checkLargeParameter(count);391 GenericArray<T> res(count);392 for (T& t: res) {393 t = choice();394 }395 return res;396}397398template<typename T>399GenericArray<T>& GenericArray<T>::operator+=(const GenericArray<T>& other) {400 if (&other == this) {401 return *this *= 2;402 }403 insert(end(), other.begin(), other.end());404 return *this;405}406407template<typename T>408GenericArray<T> GenericArray<T>::operator+(const GenericArray<T>& other) const {409 GenericArray<T> copy(*this);410 return copy += other;411}412413template<typename T>414GenericArray<T>& GenericArray<T>::operator*=(int k) {415 if (k == 0) {416 clear();417 return *this;418 }419420 this->reserve(size() * k);421422 std::copy_n(begin(), size() * (k - 1), std::back_inserter(*this));423424 return *this;425}426427template<typename T>428GenericArray<T> GenericArray<T>::operator*(int k) const {429 GenericArray<T> copy(*this);430 return copy *= k;431}432433template<typename T>434GenericArray<T>::operator std::string() const {435 static_assert(std::is_same<T, char>::value, "Must not cast"436 " TArray<T> to std::string with 'T' != 'char'");437 return std::string(begin(), end());438}439440// JNGEN_EXTERN template class GenericArray<int>;441442template<typename T>443using TArray = GenericArray<T>;444445using Array = GenericArray<int>;446using Array2d = GenericArray<jngen::GenericArray<int>>;447using Array64 = GenericArray<long long>;448using Arrayf = GenericArray<double>;449using Arrayp = GenericArray<std::pair<int, int>>;450451template<typename T>452jngen::GenericArray<T> makeArray(const std::vector<T>& values) {453 return jngen::GenericArray<T>(values);454}455456template<typename T>457jngen::GenericArray<T> makeArray(const std::initializer_list<T>& values) {458 return jngen::GenericArray<T>(values);459}460461template<typename T, typename U>462TArray<std::pair<T, U>> zip(const TArray<T>& lhs, const TArray<U>& rhs) {463 ensure(464 lhs.size() == rhs.size(),465 "In zip(a, b), a and b must have the same size");466 TArray<std::pair<T, U>> result;467 for (size_t i = 0; i < lhs.size(); ++i) {468 result.emplace_back(lhs[i], rhs[i]);469 }470 return result;471}472473template<typename T, typename U>474TArray<T> arrayCast(const TArray<U>& array) {475 return TArray<T>(array.begin(), array.end());476}477478template<typename T>479struct Hash<TArray<T>> {480 uint64_t operator()(const TArray<T>& elements) const {481 return Hash<std::vector<T>>{}(elements);482 }483};484485} // namespace jngen486487JNGEN_DEFINE_STD_HASH_TEMPLATE(T, jngen::TArray<T>);488489using jngen::makeArray;490using jngen::zip;491using jngen::arrayCast;492493using jngen::TArray;494495using jngen::Array;496using jngen::Array2d;497using jngen::Array64;498using jngen::Arrayf;499using jngen::Arrayp;