Last active
April 2, 2019 14:31
-
-
Save Sam-Belliveau/0f9ffd8eb4cf064355a394c18f8da738 to your computer and use it in GitHub Desktop.
Sorting Algorithm Visualizer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef SAMS_SUPER_COOL_SORT_ALGORITHM_VISUALIZER_2019 | |
| #define SAMS_SUPER_COOL_SORT_ALGORITHM_VISUALIZER_2019 1 | |
| #include <cstdint> // 64 bit ints | |
| #include <algorithm> // misc tools | |
| #include <random> // shuffling | |
| #include <vector> // vector | |
| // Timing | |
| #include <chrono> | |
| #include <thread> | |
| #include <SFML/Window/Event.hpp> | |
| #include <SFML/Graphics/RenderWindow.hpp> | |
| #include <SFML/Graphics/RectangleShape.hpp> | |
| #include <SFML/Graphics/Color.hpp> | |
| class Visualizer | |
| { | |
| public: // Int Type Used | |
| using IntType = std::size_t; | |
| public: // Element Type Class | |
| // This has special instructions to | |
| // draw the array when items are moved | |
| class ElementType | |
| { | |
| private: // Members | |
| Visualizer* visualizer; | |
| IntType value, timeSinceAssigned; | |
| private: // Private Rendering Functions | |
| void drawArray() const | |
| { | |
| // Don't Redraw if it is an external variable | |
| if(this >= visualizer->begin() | |
| && this < visualizer->end()) | |
| visualizer->drawArray(); | |
| } | |
| void compared() const { visualizer->incComps(); } | |
| void assigned() | |
| { | |
| timeSinceAssigned = 0; | |
| visualizer->incAssigns(); | |
| drawArray(); | |
| } | |
| public: // Public Methods used in visualizer | |
| ElementType() : value{0}, visualizer{nullptr} {} | |
| ElementType(IntType val, Visualizer* vis) | |
| : value{val}, visualizer{vis}, timeSinceAssigned{0} {}; | |
| void setVisualizer(Visualizer* vis) { visualizer = vis; } | |
| IntType getTimeSinceAssigned() { return timeSinceAssigned++; } | |
| IntType getValue() const { return value; } | |
| public: // Public Methods used in sorting | |
| ElementType(const ElementType& other) | |
| : value{other.value}, visualizer{other.visualizer} | |
| { assigned(); } | |
| ElementType& operator=(const ElementType& other) | |
| { | |
| value = other.value; | |
| visualizer = other.visualizer; | |
| assigned(); | |
| return *this; | |
| } | |
| // Support for casting into integers | |
| operator IntType() { return value; } | |
| ElementType& operator=(const IntType other) | |
| { | |
| value = other; | |
| assigned(); | |
| return *this; | |
| } | |
| friend bool operator< (const ElementType& a, const ElementType& b) | |
| { a.compared(); return a.value < b.value; } | |
| friend bool operator> (const ElementType& a, const ElementType& b) { return b < a; } | |
| friend bool operator<=(const ElementType& a, const ElementType& b) { return !(a > b); } | |
| friend bool operator>=(const ElementType& a, const ElementType& b) { return !(a < b); } | |
| friend bool operator==(const ElementType& a, const ElementType& b) { return a.value == b.value; } | |
| friend bool operator!=(const ElementType& a, const ElementType& b) { return !(a == b); } | |
| }; | |
| private: // Internal Usage | |
| // Used To Wait Certain Amounts | |
| using Clock = std::chrono::steady_clock; | |
| using DurationType = std::chrono::duration<IntType, std::milli>; | |
| using TimePoint = std::chrono::time_point<Clock>; | |
| // Used To Scale Bars to their Size | |
| constexpr static IntType WindowSize = 512; | |
| float ScaleToWindowSize(float in) | |
| { return (in * float(WindowSize)) / float(testArray.size()); } | |
| public: | |
| Visualizer() : Visualizer(0) {} | |
| Visualizer(IntType size) | |
| { | |
| sf::ContextSettings settings; | |
| settings.antialiasingLevel = 16; | |
| window.create( | |
| sf::VideoMode(WindowSize, WindowSize), | |
| "Sorting Visualizer", | |
| sf::Style::Default, | |
| settings | |
| ); | |
| comps = 0; assigns = 0; | |
| setWaitMS(0); setSize(size); | |
| } | |
| ~Visualizer() | |
| { | |
| while (window.isOpen()) | |
| { | |
| checkSFMLEvents(); | |
| drawArray(); | |
| } | |
| } | |
| void checkSFMLEvents() | |
| { | |
| sf::Event event; | |
| while (window.pollEvent(event)) | |
| if (event.type == sf::Event::Closed) | |
| window.close(); | |
| } | |
| // Draws Bar Graph | |
| void drawArray() | |
| { | |
| if(window.isOpen()) | |
| { | |
| checkSFMLEvents(); | |
| if(!setup) | |
| { | |
| TimePoint currentTime = Clock::now(); | |
| window.clear(sf::Color::Black); | |
| for(IntType i = 0; i < testArray.size(); ++i) | |
| { | |
| sf::RectangleShape bar( | |
| sf::Vector2f( | |
| ScaleToWindowSize(1), | |
| ScaleToWindowSize(testArray[i].getValue()) | |
| ) | |
| ); | |
| bar.setPosition( | |
| ScaleToWindowSize(i), | |
| ScaleToWindowSize(testArray.size() - testArray[i].getValue()) | |
| ); | |
| // Make Bar More Red If Just Moved | |
| IntType assigned = testArray[i].getTimeSinceAssigned() * 12; | |
| assigned = std::min(assigned, IntType(255)); | |
| bar.setFillColor(sf::Color(255, assigned, assigned)); | |
| window.draw(bar); | |
| } | |
| window.display(); | |
| // Waits certain amount of time, | |
| // taking rendering into account | |
| std::this_thread::sleep_until(currentTime + waitMS); | |
| } | |
| } | |
| } | |
| public: // Different Setups For The Array | |
| void sorted() | |
| { | |
| setup = true; | |
| for(IntType i = 0; i < testArray.size(); ++i) | |
| { testArray[i] = ElementType(i, this); } | |
| comps = 0; | |
| assigns = 0; | |
| setup = false; | |
| } | |
| void reversed() | |
| { | |
| setup = true; | |
| for(IntType i = 0; i < testArray.size(); ++i) | |
| { testArray[i] = ElementType(testArray.size() - i - 1, this); } | |
| comps = 0; | |
| assigns = 0; | |
| setup = false; | |
| } | |
| void randomize(IntType seed = 0x3243F6A8885A308D) | |
| { | |
| sorted(); | |
| setup = true; | |
| std::mt19937_64 random(seed); | |
| std::shuffle(testArray.begin(), testArray.end(), random); | |
| comps = 0; | |
| assigns = 0; | |
| setup = false; | |
| } | |
| void almostsorted(IntType seed = 0x3243F6A8885A308D, IntType swapDis = 8, IntType prob = 32) | |
| { | |
| sorted(); | |
| setup = true; | |
| std::mt19937_64 random(seed); | |
| std::uniform_int_distribution<IntType> dist(0, size()/prob); | |
| for(IntType i = swapDis; i < size(); ++i) | |
| { | |
| if(dist(random) == 0) | |
| { std::swap(testArray[i], testArray[i-swapDis]); } | |
| } | |
| comps = 0; | |
| assigns = 0; | |
| setup = false; | |
| } | |
| void setSize(IntType size) | |
| { | |
| testArray.resize(size); | |
| randomize(); | |
| } | |
| void setWaitMS(IntType t) { waitMS = DurationType(t); } | |
| IntType getWaitMS() { return waitMS.count(); } | |
| public: // Element Type uses this to create tally | |
| void incComps() { ++comps; } | |
| void incAssigns() { ++assigns; } | |
| public: // Sorting Interfaces | |
| ElementType& operator[](IntType i) { return testArray[i]; } | |
| const ElementType& operator[](IntType i) const { return testArray[i]; } | |
| ElementType* begin() { return &*testArray.begin(); } | |
| const ElementType* begin() const { return &*testArray.cbegin(); } | |
| const ElementType* cbegin() const { return &*testArray.cbegin(); } | |
| ElementType* end() { return &*testArray.end(); } | |
| const ElementType* end() const { return &*testArray.cend(); } | |
| const ElementType* cend() const { return &*testArray.cend(); } | |
| IntType size() const { return testArray.size(); } | |
| IntType getComparisons() const { return comps; } | |
| IntType getAssignments() const { return assigns; } | |
| // Checks to see if array is sorted | |
| bool isSorted() const | |
| { | |
| for(IntType i = 1; i < testArray.size(); ++i) | |
| if(testArray[i].getValue() < testArray[i-1].getValue()) | |
| return false; | |
| return true; | |
| } | |
| private: | |
| sf::RenderWindow window; // Used to render things | |
| bool setup; // Used as toggle to modify array without drawing | |
| IntType comps, assigns; // Counts comparisons and assignments | |
| DurationType waitMS; | |
| using VectorType = std::vector<ElementType>; | |
| VectorType testArray; | |
| }; | |
| #endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment