Compare commits
7 Commits
d79703063f
...
d824449ddb
Author | SHA1 | Date |
---|---|---|
Bananymous | d824449ddb | |
Bananymous | 8aa137bdfe | |
Bananymous | d37b59b2df | |
Bananymous | 412aa05feb | |
Bananymous | 44358a9182 | |
Bananymous | 8516f04467 | |
Bananymous | 045a96009e |
|
@ -8,6 +8,9 @@ namespace BAN
|
|||
template<typename T, typename Container, bool CONST>
|
||||
class IteratorSimpleGeneral
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
public:
|
||||
IteratorSimpleGeneral() = default;
|
||||
template<bool CONST2, typename = enable_if_t<CONST2 == CONST || CONST>>
|
||||
|
@ -56,7 +59,8 @@ namespace BAN
|
|||
IteratorSimpleGeneral& operator--()
|
||||
{
|
||||
ASSERT(m_pointer);
|
||||
return --m_pointer;
|
||||
--m_pointer;
|
||||
return *this;
|
||||
}
|
||||
IteratorSimpleGeneral operator--(int)
|
||||
{
|
||||
|
@ -102,6 +106,8 @@ namespace BAN
|
|||
using InnerIterator = either_or_t<CONST, typename Inner::const_iterator, typename Inner::iterator>;
|
||||
using OuterIterator = either_or_t<CONST, typename Outer::const_iterator, typename Outer::iterator>;
|
||||
|
||||
using value_type = T;
|
||||
|
||||
public:
|
||||
IteratorDoubleGeneral() = default;
|
||||
template<bool CONST2, typename = enable_if_t<CONST2 == CONST || CONST>>
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
|
||||
#include <BAN/Swap.h>
|
||||
#include <BAN/Traits.h>
|
||||
|
||||
namespace BAN
|
||||
{
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
void sort_exchange(It begin, It end, Comp comp = {})
|
||||
{
|
||||
for (It lhs = begin; lhs != end; ++lhs)
|
||||
for (It rhs = lhs; ++rhs != end;)
|
||||
if (!comp(*lhs, *rhs))
|
||||
swap(*lhs, *rhs);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename It, typename Comp>
|
||||
It sort_quick_partition(It begin, It end, Comp comp)
|
||||
{
|
||||
It pivot = end; --pivot;
|
||||
|
||||
It it1 = begin;
|
||||
for (It it2 = begin; it2 != pivot; ++it2)
|
||||
{
|
||||
if (comp(*it2, *pivot))
|
||||
{
|
||||
swap(*it1, *it2);
|
||||
++it1;
|
||||
}
|
||||
}
|
||||
|
||||
swap(*it1, *pivot);
|
||||
|
||||
return it1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
void sort_quick(It begin, It end, Comp comp = {})
|
||||
{
|
||||
{
|
||||
It it = begin;
|
||||
if (it == end || ++it == end)
|
||||
return;
|
||||
}
|
||||
|
||||
It mid = detail::sort_quick_partition(begin, end, comp);
|
||||
sort_quick(begin, mid, comp);
|
||||
sort_quick(++mid, end, comp);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <BAN/Move.h>
|
||||
|
||||
namespace BAN
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
void swap(T& lhs, T& rhs)
|
||||
{
|
||||
T tmp = move(lhs);
|
||||
lhs = move(rhs);
|
||||
rhs = move(tmp);
|
||||
}
|
||||
|
||||
}
|
|
@ -28,6 +28,7 @@ set(USERSPACE_PROJECTS
|
|||
test
|
||||
test-globals
|
||||
test-framebuffer
|
||||
test-sort
|
||||
touch
|
||||
u8sum
|
||||
whoami
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <BAN/Vector.h>
|
||||
#include <BAN/Sort.h>
|
||||
#include <BAN/String.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
@ -62,44 +63,40 @@ i64 hand_score(const Hand& hand, bool joker)
|
|||
{
|
||||
if (isdigit(c))
|
||||
cnt[c - '0' + 0]++;
|
||||
else if (c == 'J')
|
||||
else if (joker && c == 'J')
|
||||
joker_count++;
|
||||
else
|
||||
cnt[c - 'A' + 10]++;
|
||||
}
|
||||
|
||||
if (!joker)
|
||||
i64 freq_max1 = 0;
|
||||
i64 freq_max2 = 0;
|
||||
for (size_t i = 0; i < 36; i++)
|
||||
{
|
||||
cnt['J' - 'A' + 10] = joker_count;
|
||||
joker_count = 0;
|
||||
if (cnt[i] > freq_max1)
|
||||
{
|
||||
freq_max2 = freq_max1;
|
||||
freq_max1 = cnt[i];
|
||||
}
|
||||
else if (cnt[i] > freq_max2)
|
||||
{
|
||||
freq_max2 = cnt[i];
|
||||
}
|
||||
}
|
||||
freq_max1 += joker_count;
|
||||
|
||||
for (size_t i = 0; i < 36; i++)
|
||||
if (cnt[i] + joker_count >= 5)
|
||||
return 6'000'000 + hand_score_no_type(hand, joker);
|
||||
|
||||
for (size_t i = 0; i < 36; i++)
|
||||
if (cnt[i] + joker_count >= 4)
|
||||
return 5'000'000 + hand_score_no_type(hand, joker);
|
||||
|
||||
for (size_t i = 0; i < 36; i++)
|
||||
for (size_t j = 0; j < 36; j++)
|
||||
if (i != j && cnt[i] + joker_count >= 3 && cnt[j] >= 2)
|
||||
return 4'000'000 + hand_score_no_type(hand, joker);
|
||||
|
||||
for (size_t i = 0; i < 36; i++)
|
||||
if (cnt[i] + joker_count >= 3)
|
||||
return 3'000'000 + hand_score_no_type(hand, joker);
|
||||
|
||||
for (size_t i = 0; i < 36; i++)
|
||||
for (size_t j = 0; j < 36; j++)
|
||||
if (i != j && cnt[i] + joker_count >= 2 && cnt[j] >= 2)
|
||||
return 2'000'000 + hand_score_no_type(hand, joker);
|
||||
|
||||
for (size_t i = 0; i < 36; i++)
|
||||
if (cnt[i] + joker_count >= 2)
|
||||
return 1'000'000 + hand_score_no_type(hand, joker);
|
||||
|
||||
if (freq_max1 == 5)
|
||||
return 6'000'000 + hand_score_no_type(hand, joker);
|
||||
if (freq_max1 == 4)
|
||||
return 5'000'000 + hand_score_no_type(hand, joker);
|
||||
if (freq_max1 == 3 && freq_max2 == 2)
|
||||
return 4'000'000 + hand_score_no_type(hand, joker);
|
||||
if (freq_max1 == 3)
|
||||
return 3'000'000 + hand_score_no_type(hand, joker);
|
||||
if (freq_max1 == 2 && freq_max2 == 2)
|
||||
return 2'000'000 + hand_score_no_type(hand, joker);
|
||||
if (freq_max1 == 2)
|
||||
return 1'000'000 + hand_score_no_type(hand, joker);
|
||||
return hand_score_no_type(hand, joker);
|
||||
}
|
||||
|
||||
|
@ -113,33 +110,21 @@ i64 puzzle(FILE* fp, bool joker)
|
|||
BAN::StringView line(buffer);
|
||||
if (line.size() < 7)
|
||||
continue;
|
||||
|
||||
Hand hand;
|
||||
hand.hand = line.substring(0, 5);
|
||||
hand.bid = parse_i64(line.substring(6));
|
||||
MUST(hands.push_back(hand));
|
||||
MUST(hands.emplace_back(
|
||||
line.substring(0, 5),
|
||||
parse_i64(line.substring(6))
|
||||
));
|
||||
}
|
||||
|
||||
// Very slow sorting algorithm
|
||||
for (size_t i = 0; i < hands.size(); i++)
|
||||
{
|
||||
i64 l_score = hand_score(hands[i], joker);
|
||||
for (size_t j = i + 1; j < hands.size(); j++)
|
||||
{
|
||||
i64 r_score = hand_score(hands[j], joker);
|
||||
if (r_score > l_score)
|
||||
{
|
||||
Hand tmp = BAN::move(hands[i]);
|
||||
hands[i] = BAN::move(hands[j]);
|
||||
hands[j] = BAN::move(tmp);
|
||||
l_score = r_score;
|
||||
}
|
||||
BAN::sort_quick(hands.begin(), hands.end(),
|
||||
[joker] (const Hand& lhs, const Hand& rhs) {
|
||||
return hand_score(lhs, joker) < hand_score(rhs, joker);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
i64 score = 0;
|
||||
for (size_t i = 0; i < hands.size(); i++)
|
||||
score += (hands.size() - i) * hands[i].bid;
|
||||
score += (i + 1) * hands[i].bid;
|
||||
return score;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
cmake_minimum_required(VERSION 3.26)
|
||||
|
||||
project(test-sort CXX)
|
||||
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-sort ${SOURCES})
|
||||
target_compile_options(test-sort PUBLIC -O2 -g)
|
||||
target_link_libraries(test-sort PUBLIC libc)
|
||||
|
||||
add_custom_target(test-sort-install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/test-sort ${BANAN_BIN}/
|
||||
DEPENDS test-sort
|
||||
)
|
|
@ -0,0 +1,41 @@
|
|||
#include <BAN/Vector.h>
|
||||
#include <BAN/Sort.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
template<typename T>
|
||||
bool is_sorted(BAN::Vector<T>& vec)
|
||||
{
|
||||
for (size_t i = 0; i < vec.size() - 1; i++)
|
||||
if (vec[i] > vec[i + 1])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define CURRENT_NS() ({ timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); ts.tv_sec * 1'000'000'000 + ts.tv_nsec; })
|
||||
|
||||
#define TEST(name, function, count) do { \
|
||||
BAN::Vector<int> ivec(count, 0); \
|
||||
for (int& i : ivec) \
|
||||
i = rand() % 100; \
|
||||
uint64_t start_ns = CURRENT_NS(); \
|
||||
function(ivec.begin(), ivec.end()); \
|
||||
uint64_t end_ns = CURRENT_NS(); \
|
||||
uint64_t dur_us = (end_ns - start_ns) / 1000; \
|
||||
printf(name " (" #count "): %s\n", is_sorted(ivec) ? "success" : "fail"); \
|
||||
printf(" took %" PRIu64 ".%03" PRIu64 " ms\n", dur_us / 1000, dur_us % 1000); \
|
||||
} while (0)
|
||||
|
||||
int main()
|
||||
{
|
||||
srand(time(0));
|
||||
TEST("exchange sort", BAN::sort_exchange, 100);
|
||||
TEST("exchange sort", BAN::sort_exchange, 1000);
|
||||
TEST("exchange sort", BAN::sort_exchange, 10000);
|
||||
|
||||
TEST("quick sort", BAN::sort_quick, 100);
|
||||
TEST("quick sort", BAN::sort_quick, 1000);
|
||||
TEST("quick sort", BAN::sort_quick, 10000);
|
||||
}
|
Loading…
Reference in New Issue