Skip to content

Instantly share code, notes, and snippets.

@minghao912
Last active July 31, 2021 05:21
Show Gist options
  • Save minghao912/6d4897f922de4a6a2093764b3674063e to your computer and use it in GitHub Desktop.
Save minghao912/6d4897f922de4a6a2093764b3674063e to your computer and use it in GitHub Desktop.
Checks if a given hand is a valid Mahjong hand
#include "CheckValidity.h"
#include <iostream>
using namespace std;
int main() {
vector<int> hand = {1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6};
string validHand = (isValidHand(hand)) ? "true" : "false";
cout << "Hand is valid: " << validHand << endl;
return 0;
}
bool isValidHand(vector<int> hand) {
// Get the possible pair value
vector<int> pairPossibleValue;
int remainder = getSum(&hand) % 3;
if (remainder == 0)
pairPossibleValue = {3, 6, 9};
else if (remainder == 1)
pairPossibleValue = {2, 5, 8};
else if (remainder == 2)
pairPossibleValue = {1, 4, 7};
// Remove the pair from hand, if the pair is in the hand
vector<vector<int>> handsWithPairRemoved;
for (int value : pairPossibleValue) {
auto handWithPairRemoved = removeValue(hand, value);
if (handWithPairRemoved)
handsWithPairRemoved.push_back(*handWithPairRemoved);
}
// Check if the remaining hand can form triplets
for (vector<int> h : handsWithPairRemoved)
if (checkRemaining(h)) // If any one of the remaining hands are valid, then the hand is valid
return true;
// None of the hands with pair removed are valid, so return false
return false;
}
int getSum(vector<int>* const hand) {
int sum;
for (int i : *hand)
sum += i;
return sum;
}
optional<vector<int>> removeValue(vector<int> hand, int value) {
int numRemoved = 0;
for (auto it = hand.begin(); it != hand.end(); ) {
if (numRemoved == 2)
break;
if (*it == value) {
hand.erase(it);
numRemoved++;
} else it++;
}
if (numRemoved < 2)
return nullopt;
return hand;
}
bool checkRemaining(vector<int> hand) {
for (auto it = hand.begin(); it != hand.end(); ) {
if (hand.empty())
return true;
if (it + 2 == hand.end())
break;
int curPos = *it;
int posOne = *(it + 1);
int posTwo = *(it + 2);
// Check if there are pong or chi and remove them if so
if (curPos == posOne && posOne == posTwo) {
hand.erase(it + 2);
hand.erase(it + 1);
hand.erase(it);
} else if (curPos == posOne - 1 && posOne == posTwo - 1) {
hand.erase(it + 2);
hand.erase(it + 1);
hand.erase(it);
} else it++; // Increment one if no patterns found
}
// If valid, triplets would all be removed, leaving empty hand
return hand.empty();
}
#pragma once
#include <vector>
#include <optional>
bool isValidHand(std::vector<int> hand);
int getSum(std::vector<int>* const hand);
std::optional<std::vector<int>> removeValue(std::vector<int> hand, int value);
bool checkRemaining(std::vector<int> hand);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment