Compare commits

..

No commits in common. "d824449ddb8bd568d643a4d77238f55bf1723aa9" and "d79703063f94b75b5d090073b108d6856995811c" have entirely different histories.

7 changed files with 53 additions and 175 deletions

View File

@ -8,9 +8,6 @@ namespace BAN
template<typename T, typename Container, bool CONST> template<typename T, typename Container, bool CONST>
class IteratorSimpleGeneral class IteratorSimpleGeneral
{ {
public:
using value_type = T;
public: public:
IteratorSimpleGeneral() = default; IteratorSimpleGeneral() = default;
template<bool CONST2, typename = enable_if_t<CONST2 == CONST || CONST>> template<bool CONST2, typename = enable_if_t<CONST2 == CONST || CONST>>
@ -59,8 +56,7 @@ namespace BAN
IteratorSimpleGeneral& operator--() IteratorSimpleGeneral& operator--()
{ {
ASSERT(m_pointer); ASSERT(m_pointer);
--m_pointer; return --m_pointer;
return *this;
} }
IteratorSimpleGeneral operator--(int) IteratorSimpleGeneral operator--(int)
{ {
@ -106,8 +102,6 @@ namespace BAN
using InnerIterator = either_or_t<CONST, typename Inner::const_iterator, typename Inner::iterator>; 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 OuterIterator = either_or_t<CONST, typename Outer::const_iterator, typename Outer::iterator>;
using value_type = T;
public: public:
IteratorDoubleGeneral() = default; IteratorDoubleGeneral() = default;
template<bool CONST2, typename = enable_if_t<CONST2 == CONST || CONST>> template<bool CONST2, typename = enable_if_t<CONST2 == CONST || CONST>>

View File

@ -1,57 +0,0 @@
#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);
}
}

View File

@ -1,16 +0,0 @@
#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);
}
}

View File

@ -28,7 +28,6 @@ set(USERSPACE_PROJECTS
test test
test-globals test-globals
test-framebuffer test-framebuffer
test-sort
touch touch
u8sum u8sum
whoami whoami

View File

@ -1,5 +1,4 @@
#include <BAN/Vector.h> #include <BAN/Vector.h>
#include <BAN/Sort.h>
#include <BAN/String.h> #include <BAN/String.h>
#include <ctype.h> #include <ctype.h>
@ -63,40 +62,44 @@ i64 hand_score(const Hand& hand, bool joker)
{ {
if (isdigit(c)) if (isdigit(c))
cnt[c - '0' + 0]++; cnt[c - '0' + 0]++;
else if (joker && c == 'J') else if (c == 'J')
joker_count++; joker_count++;
else else
cnt[c - 'A' + 10]++; cnt[c - 'A' + 10]++;
} }
i64 freq_max1 = 0; if (!joker)
i64 freq_max2 = 0;
for (size_t i = 0; i < 36; i++)
{ {
if (cnt[i] > freq_max1) cnt['J' - 'A' + 10] = joker_count;
{ joker_count = 0;
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 (freq_max1 == 5) if (cnt[i] + joker_count >= 5)
return 6'000'000 + hand_score_no_type(hand, joker); return 6'000'000 + hand_score_no_type(hand, joker);
if (freq_max1 == 4)
return 5'000'000 + hand_score_no_type(hand, joker); for (size_t i = 0; i < 36; i++)
if (freq_max1 == 3 && freq_max2 == 2) if (cnt[i] + joker_count >= 4)
return 4'000'000 + hand_score_no_type(hand, joker); return 5'000'000 + hand_score_no_type(hand, joker);
if (freq_max1 == 3)
return 3'000'000 + hand_score_no_type(hand, joker); for (size_t i = 0; i < 36; i++)
if (freq_max1 == 2 && freq_max2 == 2) for (size_t j = 0; j < 36; j++)
return 2'000'000 + hand_score_no_type(hand, joker); if (i != j && cnt[i] + joker_count >= 3 && cnt[j] >= 2)
if (freq_max1 == 2) return 4'000'000 + hand_score_no_type(hand, joker);
return 1'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);
return hand_score_no_type(hand, joker); return hand_score_no_type(hand, joker);
} }
@ -110,21 +113,33 @@ i64 puzzle(FILE* fp, bool joker)
BAN::StringView line(buffer); BAN::StringView line(buffer);
if (line.size() < 7) if (line.size() < 7)
continue; continue;
MUST(hands.emplace_back(
line.substring(0, 5), Hand hand;
parse_i64(line.substring(6)) hand.hand = line.substring(0, 5);
)); hand.bid = parse_i64(line.substring(6));
MUST(hands.push_back(hand));
} }
BAN::sort_quick(hands.begin(), hands.end(), // Very slow sorting algorithm
[joker] (const Hand& lhs, const Hand& rhs) { for (size_t i = 0; i < hands.size(); i++)
return hand_score(lhs, joker) < hand_score(rhs, joker); {
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;
}
} }
); }
i64 score = 0; i64 score = 0;
for (size_t i = 0; i < hands.size(); i++) for (size_t i = 0; i < hands.size(); i++)
score += (i + 1) * hands[i].bid; score += (hands.size() - i) * hands[i].bid;
return score; return score;
} }

View File

@ -1,16 +0,0 @@
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
)

View File

@ -1,41 +0,0 @@
#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);
}