Kumite (ko͞omiˌtā) is the practice of taking techniques learned from Kata and applying them through the act of freestyle sparring.
You can create a new kumite by providing some initial code and optionally some test cases. From there other warriors can spar with you, by enhancing, refactoring and translating your code. There is no limit to how many warriors you can spar with.
A great use for kumite is to begin an idea for a kata as one. You can collaborate with other code warriors until you have it right, then you can convert it to a kata.
Constructor situation is a bit better now. Thunks are now copyable and are more flexibly constructible.
Background
C++ recreation of the Thunk API from this Kata.
Test cases are included to verify if it works as expected. The full extent of the class is used in those test cases.
#include <tuple> #include <string> #include <vector> #include <utility> Describe(fixed_test_cases) { It(basic_thunk_tests) { // Currently stores 3. Thunk num1 = MakeThunk::now(3); // Represents the future result of multiplying num1's value by 2 (i.e., 3 * 2 ==> 6). Thunk num2 = num1.chain([](auto n) { return n * 2; }); // Delayed computation of the number formed by concatenating num1 and num2 as strings. // Note: Since the function captures by reference, it's impure. However, this can allow us to check if computation is actually delayed. const Thunk num3 = MakeThunk::delay([&] { return std::stoi(std::to_string(num1.get()) + std::to_string(num2.get())); }); Assert::That(num2.get(), Equals(6)); Assert::That(num1.get(), Equals(3)); // Change num2 to 0. num2 = MakeThunk::delay([] { return 0; }); // Since Thunks delay computation, it actually computes 30 (up to date) and not 36 (outdated). Assert::That(num3.get(), Equals(30)); // Change num1 to 4. num1 = MakeThunk::now(4); // Thunk only evaluated once - unaffected by change. Remains 30 instead of 40. Assert::That(num3.get(), Equals(30)); // Works with regular old functions (non-functors) too. const Thunk num4 = MakeThunk::delay(return_24); Assert::That(num4.get(), Equals(24)); } It(can_chain_different_types) { // First chain returns int, second returns std::pair<int, int>, third returns string. const Thunk birthday_msg = MakeThunk::now(24) .chain([](auto n) { return std::pair{ n, n + 1 }; }) .chain([](auto ages) { return "Do you know what is funnier than " + std::to_string(ages.first) + "? " + std::to_string(ages.second) + "!"; }); Assert::That(birthday_msg.get(), Equals("Do you know what is funnier than 24? 25!")); } It(allows_cyclic_ref) { using LazyPair = std::pair<int, Thunk<int>>; // Second item of pair is 5 times the first (i.e., 10 * 5 == 50). LazyPair lazy_pair{ 10, MakeThunk::delay([&] { return lazy_pair.first * 5; })}; Assert::That(lazy_pair.second.get(), Equals(50)); } It(successfully_extends_lifetime) { Thunk<int> remaining_thunk{}; // Scope to restrict the lifetime of `expiring_thunk`. `remaining_thunk` depends on its data. { Thunk expiring_thunk = MakeThunk::now(3); remaining_thunk = expiring_thunk.chain([](auto n) { return n * 2; }); } // Thunk class should successfully extend the lifetime of the data of other Thunks it depends on. Assert::That(remaining_thunk.get(), Equals(6)); } It(thunk_is_copyable) { Thunk<const char*> c_str_thunk = MakeThunk::now("Yooooo"); Thunk<std::string> str_thunk_1 = c_str_thunk; Assert::That(str_thunk_1.get(), Equals("Yooooo")); Assert::That(std::is_same_v<std::string, std::decay_t<decltype(str_thunk_1.get())>>); Assert::That(str_thunk_1.get().c_str() != c_str_thunk.get()); Thunk<std::string> str_thunk_2 = MakeThunk::now("yo"); Assert::That(str_thunk_2.get(), Equals("yo")); Assert::That(std::is_same_v<std::string, std::decay_t<decltype(str_thunk_2.get())>>); Thunk<std::string> str_thunk_cpy = str_thunk_1; // If the types are the same, reuse the same stored data. Assert::That(&str_thunk_cpy.get() == &str_thunk_1.get()); Assert::That(str_thunk_1.get().c_str() == str_thunk_cpy.get().c_str()); } It(all_thunk_constructors_work_correctly) { const Thunk<int> num5{ return_24 }; // return_24 is a regular non-functor function. Assert::That(num5.get(), Equals(24)); const auto default_thunk_1 = MakeThunk::now_in_place<std::pair<int, int>>(); const Thunk<std::pair<int, int>> default_thunk_2{}; const Thunk default_thunk_3 = MakeThunk::now(std::pair<int, int>{}); const Thunk<std::pair<int, int>> default_thunk_4{ std::in_place }; Assert::That(default_thunk_1.get() == default_thunk_2.get() and default_thunk_2.get() == default_thunk_3.get() and default_thunk_3.get() == default_thunk_4.get()); const auto str_thunk = MakeThunk::now_in_place<std::string>("hey"); Assert::That(str_thunk.get(), Equals("hey")); const auto three_b_thunk = MakeThunk::now_in_place<std::string>(3, 'B'); Assert::That(three_b_thunk.get(), Equals("BBB")); const auto vec_thunk = MakeThunk::now_in_place<std::vector<int>>(std::initializer_list<int>{ 1, 2, 3 }); Assert::That(vec_thunk.get(), Equals(std::vector{ 1, 2, 3 })); const Thunk<std::string> four_a_thunk{ std::in_place, 4, 'A' }; Assert::That(four_a_thunk.get(), Equals("AAAA")); const Thunk<std::pair<int, char>> pair_thunk{ std::in_place, 2, 'z' }; Assert::That(pair_thunk.get(), Equals(std::pair{ 2, 'z' })); const auto tuple_thunk = MakeThunk::now_in_place<std::tuple<int, char, int, int>>(-2, 'f', 2000, 9); Assert::That(tuple_thunk.get(), Equals(std::tuple{ -2, 'f', 2000, 9 })); } private: // Regular old function. static int return_24() { return 24; } };
- #include <tuple>
- #include <string>
- #include <vector>
- #include <utility>
- Describe(fixed_test_cases)
- {
- It(basic_thunk_tests)
- {
- // Currently stores 3.
- Thunk num1 = MakeThunk::now(3);
- // Represents the future result of multiplying num1's value by 2 (i.e., 3 * 2 ==> 6).
- Thunk num2 = num1.chain([](auto n) { return n * 2; });
- // Delayed computation of the number formed by concatenating num1 and num2 as strings.
- // Note: Since the function captures by reference, it's impure. However, this can allow us to check if computation is actually delayed.
- const Thunk num3 = MakeThunk::delay([&] { return std::stoi(std::to_string(num1.get()) + std::to_string(num2.get())); });
- Assert::That(num2.get(), Equals(6));
- Assert::That(num1.get(), Equals(3));
- // Change num2 to 0.
- num2 = MakeThunk::delay([] { return 0; });
- // Since Thunks delay computation, it actually computes 30 (up to date) and not 36 (outdated).
- Assert::That(num3.get(), Equals(30));
- // Change num1 to 4.
- num1 = MakeThunk::now(4);
// Thunk only computed once - unaffected by change. Remains 30 instead of 40.- // Thunk only evaluated once - unaffected by change. Remains 30 instead of 40.
- Assert::That(num3.get(), Equals(30));
- // Works with regular old functions (non-functors) too.
- const Thunk num4 = MakeThunk::delay(return_24);
- Assert::That(num4.get(), Equals(24));
- }
- It(can_chain_different_types)
- {
- // First chain returns int, second returns std::pair<int, int>, third returns string.
- const Thunk birthday_msg = MakeThunk::now(24)
- .chain([](auto n) { return std::pair{ n, n + 1 }; })
- .chain([](auto ages) { return "Do you know what is funnier than " + std::to_string(ages.first) + "? " + std::to_string(ages.second) + "!"; });
- Assert::That(birthday_msg.get(), Equals("Do you know what is funnier than 24? 25!"));
- }
- It(allows_cyclic_ref)
- {
- using LazyPair = std::pair<int, Thunk<int>>;
- // Second item of pair is 5 times the first (i.e., 10 * 5 == 50).
- LazyPair lazy_pair{ 10, MakeThunk::delay([&] { return lazy_pair.first * 5; })};
- Assert::That(lazy_pair.second.get(), Equals(50));
- }
- It(successfully_extends_lifetime)
- {
- Thunk<int> remaining_thunk{};
- // Scope to restrict the lifetime of `expiring_thunk`. `remaining_thunk` depends on its data.
- {
- Thunk expiring_thunk = MakeThunk::now(3);
- remaining_thunk = expiring_thunk.chain([](auto n) { return n * 2; });
- }
- // Thunk class should successfully extend the lifetime of the data of other Thunks it depends on.
- Assert::That(remaining_thunk.get(), Equals(6));
- }
- It(thunk_is_copyable)
- {
- Thunk<const char*> c_str_thunk = MakeThunk::now("Yooooo");
- Thunk<std::string> str_thunk_1 = c_str_thunk;
- Assert::That(str_thunk_1.get(), Equals("Yooooo"));
- Assert::That(std::is_same_v<std::string, std::decay_t<decltype(str_thunk_1.get())>>);
- Assert::That(str_thunk_1.get().c_str() != c_str_thunk.get());
- Thunk<std::string> str_thunk_2 = MakeThunk::now("yo");
- Assert::That(str_thunk_2.get(), Equals("yo"));
- Assert::That(std::is_same_v<std::string, std::decay_t<decltype(str_thunk_2.get())>>);
- Thunk<std::string> str_thunk_cpy = str_thunk_1;
- // If the types are the same, reuse the same stored data.
- Assert::That(&str_thunk_cpy.get() == &str_thunk_1.get());
- Assert::That(str_thunk_1.get().c_str() == str_thunk_cpy.get().c_str());
- }
- It(all_thunk_constructors_work_correctly)
- {
- const Thunk<int> num5{ return_24 }; // return_24 is a regular non-functor function.
- Assert::That(num5.get(), Equals(24));
- const auto default_thunk_1 = MakeThunk::now_in_place<std::pair<int, int>>();
- const Thunk<std::pair<int, int>> default_thunk_2{};
- const Thunk default_thunk_3 = MakeThunk::now(std::pair<int, int>{});
- const Thunk<std::pair<int, int>> default_thunk_4{ std::in_place };
- Assert::That(default_thunk_1.get() == default_thunk_2.get() and default_thunk_2.get() == default_thunk_3.get() and default_thunk_3.get() == default_thunk_4.get());
- const auto str_thunk = MakeThunk::now_in_place<std::string>("hey");
- Assert::That(str_thunk.get(), Equals("hey"));
- const auto three_b_thunk = MakeThunk::now_in_place<std::string>(3, 'B');
- Assert::That(three_b_thunk.get(), Equals("BBB"));
- const auto vec_thunk = MakeThunk::now_in_place<std::vector<int>>(std::initializer_list<int>{ 1, 2, 3 });
- Assert::That(vec_thunk.get(), Equals(std::vector{ 1, 2, 3 }));
- const Thunk<std::string> four_a_thunk{ std::in_place, 4, 'A' };
- Assert::That(four_a_thunk.get(), Equals("AAAA"));
- const Thunk<std::pair<int, char>> pair_thunk{ std::in_place, 2, 'z' };
- Assert::That(pair_thunk.get(), Equals(std::pair{ 2, 'z' }));
- const auto tuple_thunk = MakeThunk::now_in_place<std::tuple<int, char, int, int>>(-2, 'f', 2000, 9);
- Assert::That(tuple_thunk.get(), Equals(std::tuple{ -2, 'f', 2000, 9 }));
- }
- private:
- // Regular old function.
- static int return_24() { return 24; }
- };
worldName = "World" greetWord = "Hello" sign = "!" spacing = " " comma = "," print(greetWord+spacing+comma+spacing+worldName+spacing+sign+sign)
- worldName = "World"
- greetWord = "Hello"
- sign = "!"
- spacing = " "
- comma = ","
print(greetWord+comma+spacing+worldName+sign)- print(greetWord+spacing+comma+spacing+worldName+spacing+sign+sign)
This algorithm of 'sum()' is SFINAE-friendly. By first testing if the corresponding types can be added with the type trait 'has_plus' because some types doesn't have the 'operator+' defined. If for any reason, the types doesn't have the addition operator available, the function will be disabled via 'std::enable_if' and will be discarded by SFINAE. In constrast, if the types can be added, the 'std::enable_if' trait will enable the function and returning the corresponding type of add the two types with the 'plus_result' trait.
#include <vector> #include <numeric> #include <type_traits> #include <utility> namespace { template<typename, typename, typename = void> struct has_plus : std::false_type {}; template<typename T1, typename T2> struct has_plus<T1, T2, std::void_t<decltype(std::declval<T1>() + std::declval<T2>())>> : std::true_type {}; template<typename T1, typename T2> inline constexpr bool has_plus_v = has_plus<T1, T2>::value; template<typename T1, typename T2, bool = has_plus_v<T1, T2>> struct plus_result { using type = decltype(std::declval<T1>() + std::declval<T2>()); }; template<typename T1, typename T2> struct plus_result<T1, T2, false> {}; template<typename T1, typename T2> using plus_result_t = typename plus_result<T1, T2>::type; template<typename T = double, typename = std::enable_if_t<has_plus_v<T, T>>> plus_result_t<T, T> sum(const std::vector<T>& v) { return std::accumulate(v.cbegin(), v.cend(), T{}); } }
- #include <vector>
- #include <numeric>
- #include <type_traits>
- #include <utility>
template <typename T> using add_t=decltype(T() + T());- namespace
- {
- template<typename, typename, typename = void>
- struct has_plus : std::false_type {};
template <typename T = double>add_t<T> sum(const std::vector<T>& v) {return std::accumulate(v.cbegin(),v.cend(),add_t<T>{0});- template<typename T1, typename T2>
- struct has_plus<T1, T2, std::void_t<decltype(std::declval<T1>() + std::declval<T2>())>> : std::true_type {};
- template<typename T1, typename T2>
- inline constexpr bool has_plus_v = has_plus<T1, T2>::value;
- template<typename T1, typename T2, bool = has_plus_v<T1, T2>>
- struct plus_result
- {
- using type = decltype(std::declval<T1>() + std::declval<T2>());
- };
- template<typename T1, typename T2>
- struct plus_result<T1, T2, false> {};
- template<typename T1, typename T2>
- using plus_result_t = typename plus_result<T1, T2>::type;
- template<typename T = double, typename = std::enable_if_t<has_plus_v<T, T>>>
- plus_result_t<T, T> sum(const std::vector<T>& v)
- {
- return std::accumulate(v.cbegin(), v.cend(), T{});
- }
- }
using System.Linq; public class Program { public static int FindSquaresInArray(int[] arr) => arr.Sum(x => x * x); }
- using System.Linq;
- public class Program
- {
public static int FindSquaresInArray(int[] arr) => arr.Sum(x => x*x);- public static int FindSquaresInArray(int[] arr) => arr.Sum(x => x * x);
- }
Constants should be in capital.
import zlib L='L1' exec(str(zlib.decompress(bytes("xÚMP=oÂ0ý+¯YXC[u@B,h§v©ÄâØpqìÈw.Eÿ½DåÅzw÷¾~eL×8·ª±Í¾\"ªº_UØ1HÛÒy!³¤äXÕ¬>wM\nj¶Ú¤®ÏÄ`ò Ê9wI-äàyè/>;lr´ØÅÏ+¬;Ãx~yxÜyBðj¼R@|¥V 8rRCmv´[ù2IL¢5½9ß»ë`'zbä~·Àïú@àÊÔÂß e$ßUããT²½&»¼§Lc¦,ø1Ù(ð¼KPìÔ\nERvÐÜõ&¨Ù£t£~C©òNÿZ5QÇklÌäý½uíq÷k¼Ìö@ö/Õ¸ª",encoding=L)),L))
- import zlib
l='L1'exec(str(zlib.decompress(bytes("xÚMP=oÂ0ý+¯YXC[u@B,h§v©ÄâØpqìÈw.Eÿ½DåÅzw÷¾~eL×8·ª±Í¾\"ªº_UØ1HÛÒy!³¤äXÕ¬>wMj¶Ú¤®ÏÄ`ò Ê9wI-äàyè/>;lr´ØÅÏ+¬;Ãx~yxÜyBðj¼R@|¥V 8rRCmv´[ù2IL¢5½9ß»ë`'zbä~·Àïú@àÊÔÂß e$ßUããT²½&»¼§Lc¦,ø1Ù(ð¼KPìÔERvÐÜõ&¨Ù£t£~C©òNÿZ5QÇklÌäý½uíq÷k¼Ìö@ö/Õ¸ª",encoding=l)),l))- L='L1'
- exec(str(zlib.decompress(bytes("xÚMP=oÂ0ý+¯YXC[u@B,h§v©ÄâØpqìÈw.Eÿ½DåÅzw÷¾~eL×8·ª±Í¾\"ªº_UØ1HÛÒy!³¤äXÕ¬>wM
- j¶Ú¤®ÏÄ`ò Ê9wI-äàyè/>;lr´ØÅÏ+¬;Ãx~yxÜyBðj¼R@|¥V 8rRCmv´[ù2IL¢5½9ß»ë`'zbä~·Àïú@àÊÔÂß e$ßUããT²½&»¼§Lc¦,ø1Ù(ð¼KPìÔ
- ERvÐÜõ&¨Ù£t£~C©òNÿZ5QÇklÌäý½uíq÷k¼Ìö@ö/Õ¸ª",encoding=L)),L))
import java.util.Arrays; import java.math.BigInteger; public class MaxNumber { public static BigInteger print(long number) { int[] digits = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; for (char digit : Long.toString(number).toCharArray()) { digits[digit - '0']++; } BigInteger sum = BigInteger.ZERO; int i = 9; while(i >= 0) { if (digits[i] == 0) { i--; } else { digits[i]--; sum = sum.multiply(BigInteger.TEN).add(BigInteger.valueOf(i)); } } return sum; } }
- import java.util.Arrays;
- import java.math.BigInteger;
- public class MaxNumber {
public static long print(long number) {- public static BigInteger print(long number) {
- int[] digits = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- for (char digit : Long.toString(number).toCharArray()) {
- digits[digit - '0']++;
- }
long sum = 0;- BigInteger sum = BigInteger.ZERO;
- int i = 9;
- while(i >= 0) {
- if (digits[i] == 0) {
- i--;
- } else {
- digits[i]--;
sum = (10 * sum) + i;- sum = sum.multiply(BigInteger.TEN).add(BigInteger.valueOf(i));
- }
- }
- return sum;
- }
- }
import org.junit.Test; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.logging.Logger; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.math.BigInteger; public class MaxNumberTest { private static final Logger logger = Logger.getLogger(MaxNumberTest.class.getName()); // Adjust as needed public static final double MAX_EXECUTION_TIME_MS = 5; public static final int MAX_WAIT_TIME_LOOP_IN_SEC = 10; public static String concatenateCharacters(List<Character> charList) { StringBuilder sb = new StringBuilder(); for (Character ch : charList) { sb.append(ch); } return sb.toString(); } @Test public void testFour() { assertEquals(BigInteger.valueOf(4), MaxNumber.print(4)); } @Test public void testTwelve() { assertEquals(BigInteger.valueOf(21), MaxNumber.print(12)); } @Test public void testOneHundred() { assertEquals(BigInteger.valueOf(110), MaxNumber.print(101)); } @Test public void testHuge1() { assertEquals(BigInteger.valueOf(754000000000000000L), MaxNumber.print(400000005000007000L)); } @Test public void testHuge2() { assertEquals(BigInteger.valueOf(988777666444322200L), MaxNumber.print(307778062924466824L)); } @Test public void testMaxInt() { assertTrue(MaxNumber.print(Long.MAX_VALUE).compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 0); } @Test public void testFunctionTimePerformance() { ThreadLocalRandom random = ThreadLocalRandom.current(); long beforeWarmup = System.currentTimeMillis(); // warmup of CPU cache for (int i = 0; i < 200; i++) { MaxNumber.print(random.nextLong(0, Long.MAX_VALUE / 10)); } long afterWarmup = System.currentTimeMillis(); double warmupTimeSec = (afterWarmup - beforeWarmup) / 1_000D; assertTrue(warmupTimeSec < MAX_WAIT_TIME_LOOP_IN_SEC, "Rough execution time is too high: " + String.format("%.1f", warmupTimeSec * 5) + "ms"); // factor of 5 is due to 1000 (ms/s) / 200 iterations long startTime = System.nanoTime(); int iterations = 10_000; // ------ for (int i = 0; i < iterations; i++) { MaxNumber.print(random.nextLong(0, Long.MAX_VALUE / 10)); } // ------ long endTime = System.nanoTime(); // Calculate the execution time in milliseconds long totalExecutionTimeMs = (endTime - startTime) / 1_000_000; double avgExecTimeMs = totalExecutionTimeMs / (double) iterations; logger.info("Average execution time was: " + String.format("%.3f", avgExecTimeMs) + "ms"); assertTrue(avgExecTimeMs <= MAX_EXECUTION_TIME_MS, "Execution time exceeded the " + MAX_EXECUTION_TIME_MS + "ms limit"); } @Test public void testRandomValues() { char[] almostAllDigits = new char[]{'0','0','1','2','2','3','3','3','4','5','6','7','7','8','8','9','9'}; for (int i = 0; i < 100; i++) { List<Character> allDigitList = new ArrayList<>(); for (char digit : almostAllDigits) { allDigitList.add(digit); } Collections.shuffle(allDigitList); allDigitList.add(0, '1'); // to prevent starting with 0 String shuffledDigits = concatenateCharacters(allDigitList); long randomNumber = Long.parseLong(shuffledDigits); BigInteger actualMaxNumber = MaxNumber.print(randomNumber); BigInteger expectedMaxNumber = BigInteger.valueOf(998877654333221100L); // allMostAllDigits joined with {'1'}, in descending order assertEquals(expectedMaxNumber, actualMaxNumber, "Expected: " + expectedMaxNumber + " from " + randomNumber +", but got: " + actualMaxNumber); } } }
- import org.junit.Test;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- import java.util.concurrent.ThreadLocalRandom;
- import java.util.logging.Logger;
- import static org.junit.jupiter.api.Assertions.assertEquals;
- import static org.junit.jupiter.api.Assertions.assertTrue;
- import java.math.BigInteger;
- public class MaxNumberTest {
- private static final Logger logger = Logger.getLogger(MaxNumberTest.class.getName());
- // Adjust as needed
- public static final double MAX_EXECUTION_TIME_MS = 5;
- public static final int MAX_WAIT_TIME_LOOP_IN_SEC = 10;
- public static String concatenateCharacters(List<Character> charList) {
- StringBuilder sb = new StringBuilder();
- for (Character ch : charList) {
- sb.append(ch);
- }
- return sb.toString();
- }
- @Test
- public void testFour() {
assertEquals(4, MaxNumber.print(4));- assertEquals(BigInteger.valueOf(4), MaxNumber.print(4));
- }
- @Test
- public void testTwelve() {
assertEquals(21, MaxNumber.print(12));- assertEquals(BigInteger.valueOf(21), MaxNumber.print(12));
- }
- @Test
- public void testOneHundred() {
assertEquals(110, MaxNumber.print(101));- assertEquals(BigInteger.valueOf(110), MaxNumber.print(101));
- }
- @Test
- public void testHuge1() {
assertEquals(754000000000000000L, MaxNumber.print(400000005000007000L));- assertEquals(BigInteger.valueOf(754000000000000000L), MaxNumber.print(400000005000007000L));
- }
- @Test
- public void testHuge2() {
assertEquals(988777666444322200L, MaxNumber.print(307778062924466824L));- assertEquals(BigInteger.valueOf(988777666444322200L), MaxNumber.print(307778062924466824L));
- }
- @Test
- public void testMaxInt() {
- assertTrue(MaxNumber.print(Long.MAX_VALUE).compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 0);
- }
- @Test
- public void testFunctionTimePerformance() {
- ThreadLocalRandom random = ThreadLocalRandom.current();
- long beforeWarmup = System.currentTimeMillis();
- // warmup of CPU cache
- for (int i = 0; i < 200; i++) {
- MaxNumber.print(random.nextLong(0, Long.MAX_VALUE / 10));
- }
- long afterWarmup = System.currentTimeMillis();
- double warmupTimeSec = (afterWarmup - beforeWarmup) / 1_000D;
- assertTrue(warmupTimeSec < MAX_WAIT_TIME_LOOP_IN_SEC, "Rough execution time is too high: "
- + String.format("%.1f", warmupTimeSec * 5) + "ms"); // factor of 5 is due to 1000 (ms/s) / 200 iterations
- long startTime = System.nanoTime();
- int iterations = 10_000;
- // ------
- for (int i = 0; i < iterations; i++) {
- MaxNumber.print(random.nextLong(0, Long.MAX_VALUE / 10));
- }
- // ------
- long endTime = System.nanoTime();
- // Calculate the execution time in milliseconds
- long totalExecutionTimeMs = (endTime - startTime) / 1_000_000;
- double avgExecTimeMs = totalExecutionTimeMs / (double) iterations;
- logger.info("Average execution time was: " + String.format("%.3f", avgExecTimeMs) + "ms");
- assertTrue(avgExecTimeMs <= MAX_EXECUTION_TIME_MS,
- "Execution time exceeded the " + MAX_EXECUTION_TIME_MS + "ms limit");
- }
- @Test
- public void testRandomValues() {
- char[] almostAllDigits = new char[]{'0','0','1','2','2','3','3','3','4','5','6','7','7','8','8','9','9'};
- for (int i = 0; i < 100; i++) {
- List<Character> allDigitList = new ArrayList<>();
- for (char digit : almostAllDigits) {
- allDigitList.add(digit);
- }
- Collections.shuffle(allDigitList);
- allDigitList.add(0, '1'); // to prevent starting with 0
- String shuffledDigits = concatenateCharacters(allDigitList);
- long randomNumber = Long.parseLong(shuffledDigits);
long actualMaxNumber = MaxNumber.print(randomNumber);- BigInteger actualMaxNumber = MaxNumber.print(randomNumber);
long expectedMaxNumber = 998877654333221100L; // allMostAllDigits joined with {'1'}, in descending order- BigInteger expectedMaxNumber = BigInteger.valueOf(998877654333221100L); // allMostAllDigits joined with {'1'}, in descending order
- assertEquals(expectedMaxNumber, actualMaxNumber, "Expected: " + expectedMaxNumber + " from " + randomNumber +", but got: " + actualMaxNumber);
- }
- }
- }