****
Table of Contents
A. Introduction
B. The Program Template
C. Coding Programs
(All coding problems are from the exercises in How to program
C++, How to program Visual Basis and others by Teitel)
Section 1: Build and Search Binary Trees;
Section 2: Word Search Puzzle;
Section 3: Computer-assisted dealer poker playing;
Section 4: Breaking Enigma Code
Section 5: Print 6 million Knight's Tours
Section 6: Print 1441 Sudoku Solutions from one single Sudoku puzzle
Section 7: Print 1000 Years' Calendars (1776-2775)
Section 8: Solving Hanoi Towers Problem
Section 9: Computer vs Human User in Tic-Tac-Toe games
Section 10: 8-Queen Series
Section 11: Number conversion among Arabic, English and Roman
Search Keys: ***** 1 ***** 2 ***** 3 ***** 4 ***** 5
***** 6 ***** 7 ***** 8 ***** 9 ***** 10 ***** 11
(Type a key on FIND and hit ENTER)
A. Introduction
What is Numerical Patterns Based Coding (NPBC)?
NPBC is a revolutionary approach and practice in problem solving and tools for algorithm
development. It uses numbers to represent all data and to transpose those numbers by
rules and ways. The numbers refers to 95 ASCII characters with consecutive particular
values (value 32-126. The list of 95 characters displays in ***** 4 Breaking Enigma. The 95
characters are all the non-functioning and displaying keys on a PC's keyboard. The patterns means
specially arranged and continuously changed numbers. The focus is: recognizing, organizing and
creating numerical patterns. Instead of solving problems by logic, NPBC manipulates numbers for
the same purpose. Logic solution can not use brute force in a PC. But patterns solution can do so.
The coding techques are: permutation, filtering,text files alternation, molding and substitution.
Comparing to traditional coding, NPBC is much more efficient. It processes and save
not raw data but organized and coded numbers. The programs display decoded and formatted data
and end products when the need arises.
This website formulates steps of algorithm development. Walking programers though those
steps. The site advocates one-dimensional and straight line data representation and processing
through cross-reference to replace excessive netted if, when and other loop structures.
Any data in 2 or 3 dimensional forms are changed to one dimensional form by cross reference
indices. NPBC also uses the scale-down molding technique. In the program of printing out 1440
solutions for an unusual sodoku puzzle. Instead of the puzzle board of 9x9 units and 81 squares,
and 9 values (1-9), I scale down the puzzle to 4*4 and 16 squares, and 4 values (1-4). Only after
I have solved the problem perfectly, do I make a copy of the mold and scale up the mold and solve
the problem more surely and quickly.
LBC, Logic-Based Coding, is the currently prevant coding practice. It handcuffs programmers to
ever-increased program complexity and more lengthy codes, and frequently disrupts smooth flow of
data processing. Got a data anomity? Throw a netted ifs into the codes. This is a band-aid
solution. For example, most coding programs for the knight's tour stop processing data when they
find out the knight's out of bounds and pull the knight back aboard. NPBC anticipates the out of
bounds problems and creates cross-reference indice to make it impossible for the knight to be out
of bounds by using the knight's position as the keys to retrieve only inbound and correct moves.
LBC would tell you that you can not use brute force with a PC because its limit memory. But with
NPBC, you do not worry about this problem. You just load up one piece of data from File 1 and
process it and then save it in File 2. Next you go from File 2 to File. You rotate the process.
I have developed many out of box of ideas and techniques for NBPC over the years. Those ideas
and techniques are fully explained and illustrated through the coding programs below. I do not
deviate from the talk the talk and walk the walk.
Example 1:
Hanoi Towers Puzzle
What is the minimal number of moves required to finish the job
for disk number d?
You try to solve the problem by hand and list the results.
Disk(d) Moves Formulated
2 3 pow(2,2) - 1;
3 7 pow(2,3) - 1;
4 15 pow(2,4) - 1;
5 ?
You conceptualize the pattern: pow(2,d) - 1;
d = 5; pow(2,5) - 1 = 31;
Example 2:
Building and Searching Binary Trees
Tree Structures
0 - 14 Low[0] = 0; High[0] = 14;
(Mid[0] = (Low[0] + High[0]) \ 2)
14
|
7 C0 (Cell 0) This tree has 3 levels(3 search loops).
|
________|___________
| |
C1 ___3___ ______11___ C2 value increased by 8; Level 1
| | | |
C3 1 5 C4 9 C5 13 C6 by 4; Level 2
___|__ __|___ __|__ ____|____
| | | | | | | |
0 2 4 6 8 10 12 14
C7 C8 C9 C10 C11 C12 C13 C14 by 2; Level 3
The values in a binary tree are the indexes to the array of any data types.
Binary tree follows the pattern of (low + high) \ 2 (-1/+1)
Building Tree
Low[1] = Low[0]; High[1] = Mid[0] -1; Mid[1] = (Low[1] + High[1]) \ 2
Low[2] = Mid[0] + 1; High[2] = High[0]; Mid[2] = (Low[2] + High[2]) \ 2
Conceptualize the two lines above:
n1 = 0; n2 = -1;
n1++; n2 = n2++
Low[n1] = Low[n2]; High[n1] = Mid[n2] - 1; Mid[n1] = (Low[n1] + High[n1]) \ 2
n1++;
Low[n1] = Mid[n2] + 1; High[n1] = High[n2]; Mid[n1] = (Low[n1] + High[n1]) \ 2
Searching the tree
n1 = 0; n2 = 0;
If search target < Tree[n1]
n2 = n2 + 1;
else
n2 = n2 + 2;
n1 = n1 + n2; n2 = n1;
Example 3:
Sum the wheat on the chessboard
In the chessboard(0-63), you put 1 grain of wheat in square 0, 2 grains in
square 1, and 4 grains in square 2. Keep doubling up for the nex square
until you reach square 63. Then add up the grains in all squares.
What is the sum?
Solution
You list by hand the process
Square Grains Sum
0: 1; pow(2,1) - 1; 1
1: 2; pow(2,2) - 1; 3
2: 4; pow(2,3) - 1; 7
...
63: Sum = pow(2,64) - 1;
Sum = pow(2,square + 1) - 1;
What if you can not find any pattern in the coding problem?
You make up your patterns in the form of cross-reference indices
Example 4:
Knight's Complete Tour
The knight makes L-shaped moves on the chessboard. How to tell the knight to
move that way. Suppose the tour starts on Square 0. The available moves: 10,17
Chessboard squares
0 1 2 3 4 5 6 7
8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23
You first make 2 indexes. aStart = 0. You use the 0 as the key to retrieve
the 2 moves;
mStart[0] = 0; mEnd[0] = 1; mMove[0] = 10; mMove[1] = 17
n = 0; aStart = mStart[n]; aEnd = mEnd[n];
for (k = aStart; k <= aEnd; k++)
n2 = mMove[k1];
For how to make the mMove[n] or the mStart[n] or mEnd[n], go to Coding Program,
Knight's Tour (***** 5).
Example 5:
Uiversal Callendars
There are only 14 unique calendars from 1776 to 2775. For example. the 2024 is the exact copy of
the 1776, and 2026 has the same calendar of 2015. If you use a variable in string type to
represet a calendar and de-dublicate the 1000 calendars. You get 14(0-13). You then sort the 14
strings by length. You get 2 groups of 7. Group 1(0-6): 365 in length and Group 2: 366(7-13). If
you look at the start in a calendar, you see spaces (0-6) precede number 1. If the year starts on
a Sunday, you add 0 space. If the start day is Saturday, you add 6 spaces. You sort group 1 and
then group 2. Now you get 14 universal callendars well organized. You want the 2027? It is a short
year (group 1). Since the last day of 2026 is Thursday, so 2027 starts on Friday. You pick 5 in
the calendar list. If you want 2024. It is a long year. 2024 starts on Monday (1). Long years
start at 7. You pick 8 on the list. Do not be bothered in buying the same calendar years every
year.
Example 6:
Olympic Maths
1 + 4 = 5
1 + 5 = 6
9 + 11 = 108
9 + 12 = ?
n1 * n2 + n1 = n3
9 * 12 + 9 = 117
B. Program Template
The following template is for all the coding programs in this site. You first
download a free C++ compiler from the Web, create a folder, place the program and
text files in the folder, open it and then paste the template into it. Finally you add as
many functions as you need.
#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <fstream>
#include <sstream>
#include <cstdio>
#include <conio.h>
using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::ifstream;
using std::ofstream;
using std::ostringstream;
using std::ios;
using std::strtok;
void aMain();
void SetUp1();
string mNum[95];
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
int k1,k2,n1,n2;
string x1,x2;
SetUp1();
}
void SetUp1()
{
int k1,k2;
string x1,x2;
for (k1 = 0; k1 <= 94; k1++)
{
mNum[k1] = char(k1+48);
}
}
The function QuickSort, used in this website, is copied from the Web, not my
creation.
C. Coding programs
(To avoid the compiler's memory limit, many programs adop a
2-step approach: saving massive data into text files line by line and
loading them up and processing them also line by line).
***** 1
Building and Searching a Binary Tree
The tree serves as an array index to the word list of 69888 words
e.g. the word "a" is the first word in the list, but in the tree is
many 10000s of items down. This website does not provide that word list.
But I will, within days, email the list to anyone who wants it.
int mSize,mLevel; // tree size and tree level
// the number of tree level is used as a terminater
void aMain(); // to naturally end the search loop. e.g. an array size 14
void SetUp1(); // has the tree level of 3; You use a for k1 = 0 to 3 loop
void BiIndex2(); // instead of a while loop with value-checking per loop
void BiSearch3();
void CheckIt4();
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
srand(time(0));
SetUp1();
BiIndex2();
BiSearch3();
CheckIt4();
}
void SetUp1()
{
int k1,n1, aSize = 69888;
string aWord[69889], bWord;
for (k1 = 2; k1 <= 17; k1++) // From the list size to get the tree size
{ // and the tree level.
n1 = pow(2,k1) - 2; //e.g. an array size being 7-14 needs an index
if (n1 >= aSize) break; // array of 14 and a tree level of 3 (0-3)
}
mLevel = k1 -1;
mSize = n1;
ifstream InFile("69888w.txt",ios::in); // English word list
for (k1 = 0; k1 <= 69888; k1++)
getline(InFile,aWord[k1]);
InFile.close();
ofstream OutFile("69888wr.txt", ios::out); // Randomize 0-69888 words
for (k1 = 69888; k1 >= 0; k1--) // for error-checking
{
n1 = rand() % (k1 + 1);
OutFile << aWord[n1] << endl;
aWord[n1] = aWord[k1];
}
OutFile.close();
}
void BiIndex2()
{
int k1,k2,n1;
int* Low; int* Mid; int* High;
n1 = mSize + 1;
Low = new int[n1]; Mid = new int[n1]; High = new int[n1];
Low[0] = 0; High[0] = 69888; Mid[0] = 69888 / 2;
n1 = -1;
for (k1 = 1; k1 < mSize; k1+= 2)
{
n1++; k2 = k1 + 1;
Low[k1] = Low[n1]; High[k1] = Mid[n1] - 1;
Mid[k1] = (Low[k1] + High[k1]) / 2;
Low[k2] = Mid[n1] + 1; High[k2] = High[n1];
Mid[k2] = (Low[k2] + High[k2]) / 2;
}
ofstream OutFile("Ind131070.txt",ios::out);//This is the binary tree
for (k1 = 0; k1 <= mSize; k1++)
OutFile << Mid[k1] << endl;
OutFile.close();
}
void BiSearch3()
{
int k1,n1,n2,aIndex[131071],bIndex;
string aWord[69989], bWord, Mess = "Word not found";
ifstream InFile("Ind131070.txt",ios::in); //Load the tree into an array
for (k1 = 0; k1 <= 131070; k1++)
InFile >> aIndex[k1];
InFile.close();
ifstream aInFile("69888w.txt",ios::in); //Load the word list
for (k1 = 0; k1 <= 69888; k1++)
aInFile >> aWord[k1];
aInFile.close();
cout << "Enter a word to find where it is in the word list" << endl;
cin >> bWord;
cout << "Search for the word of " << bWord << endl;
n1 = 0; n2 = 0;
for (k1 = 0; k1 <= mLevel; k1++)
{
bIndex = aIndex[n1];
if (bWord == aWord[bIndex])
{
Mess = "Word found.";
break;
}
if (bWord < aWord[bIndex])
n2 = n2 + 1;
else
n2 = n2 + 2;
n1 = n1 + n2; n2 = n1;
}
if (Mess == "Word found.")
{
cout << Mess << " " << bWord << " is in Index " << bIndex << endl;
cout << "The word in index " << bIndex << " is " << aWord[bIndex] << endl;
}
else
cout << Mess << endl;
}
void CheckIt4()// Check for errors
{
int k1,k2,n1,n2, aIndex[131071], bIndex,aNum;
string aWord[69889], bWord[69889],cWord,Mess;
ifstream aInFile("Ind131070.txt",ios::in); //Bi-tree
for (k1 = 0; k1 <= 131070; k1++)
aInFile >> aIndex[k1];
aInFile.close();
for (k2 = 0; k2 <= 69888; k2++) // Number 0-6988 must be within the tree
{
n1 = 0; n2 = 0; aNum = k2;
Mess = "Number not found.";
for (k1 = 0; k1 <= mLevel; k1++) // mLevel = 16: Maximal search attemps
{
if (aNum == aIndex[n1])
{
Mess = "Number found.";
break;
}
if (aNum < aIndex[n1])
n2 = n2 + 1;
else
n2 = n2 + 2;
n1 = n1 + n2; n2 = n1;
}
if (Mess == "Number not found.")
cout << Mess << " for " << aNum << endl;
}
ifstream bInFile("69888w.txt",ios::in);
for (k1 = 0; k1 <= 69888; k1++)
getline(bInFile,aWord[k1]);
bInFile.close();
ifstream cInFile("69888wr.txt",ios::in); //This is the randomized word list
for (k1 = 0; k1 <= 69888; k1++)
getline(cInFile,bWord[k1]);
cInFile.close();
//bWord[12345] = bWord[12345] + "**"; //Insert an error to see if it can be found
//Check if all words in the list are found
for (k2 = 0; k2 <= 69888; k2++)
{
cWord = bWord[k2];
n1 = 0; n2 = 0; Mess = "Word not found.";
for (k1 = 0; k1 <= mLevel; k1++)
{
bIndex = aIndex[n1];
if (cWord == aWord[bIndex])
{
Mess = "Word found.";
break;
}
if (cWord < aWord[bIndex])
n2 = n2 + 1;
else
n2 = n2 + 2;
n1 = n1 + n2; n2 = n1;
}
if (Mess == "Word not found.")
cout << cWord << ": "<< Mess << endl;
}
}
***** 2
Word Search Puzzles
a. Mold - the simplest compilable program
Molding As a Problem-Solving Technique
(Hand-making a mold as a template for solving word search puzzles)
Hiding Field(HF) Position Coordinates
abc 012 AA AB AC
def 345 BA BB BC
ghi 678 CA CB CC
HF is organized into 4 different types: row,column,forward and backward
diagonals. Row and column have 3 units each.Diagonals have 5 units each.
Search Words
cba (reverse order; c > b & b > a)
def
gda (reverse order)
beh
db (reverse order)
ceg
aei
fb (reverse order)
Change HF into a single string(separate a unit from another by a space)
0 10 20 30 40 50 51
0123456789012345678901234567890123456789012345678901 (aIndex[51])
012 345 678 036 147 258 0 13 246 57 8 048 15 2 37 6 (aIndex[51]'s values)
abc def ghi adg beh cfi a bd ceg fh i aei bf c dh g (HF)
111 111 111 333 333 333 2 22 222 22 2 444 44 4 44 4 (mDirec[51] for spelling)
Words' spelling directions:
For row: p0,p1,p2 (increase by 1) p0: position 0
for column p0,p3,p6 (increase by 3)
for diagonal1 p2,p4,p6 (increase by 2; Forward)
for diagonal2 p0,p4,p8 (increase by 4; Backward)
Search Word(SW) = "aei";
n1 = HF.find(SW,0);
n1 = 38; n2 = aIndex[n1] = 0;
n3 = (SW.length() - 1) * mDirec[n1] + n2; n3 = 2 * 4 + 0; n3 = 8;
Search Word aei's coordinates = Coor[n1] + "-" + Coor[n3];
Coordinates = AA-CC (First letter is AA and last letter is CC)
If a word's spelling direction is right to left or bottom to top (e.g: car = rac)
Coordinates = CC-AA.
Next you code the template into a C++ program
Finally you solve real puzzles by changing the numbers of HF's size,search word,etc.
For HF = 20 * 20, change 1,3,2 4 to 1,20,19,21, and for 21 * 21,1,21,20,22.
The program
void aMain();
void LoadPuz1();
void GetCoord2();
void GetLine3();
void FindWords4();
string Reverse5(); //Coordinates to search words
int nCoord[51] = {0},mDirec[51] = {0};
string mCoord[9],mLetter[9], mLine,mWord[16];
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
LoadPuz1();
GetCoord2();
GetLine3();
FindWords4();
}
void LoadPuz1() // Load the puzzle (Hiding Field and Search Words)
{
int k1,k2, n1;
string x1,x2;
string aNum[9], aField;
for (k1 = 0; k1 <= 8; k1++) // ASCII to char to string
aNum[k1] = char(k1+65);
n1 = -1;
for (k2 = 0; k2 <= 2; k2++) // Use 2-letter(A-I) to represent coordates
{
x1 = aNum[k2];
for (k1 = 0; k1 <= 2; k1++)
{
n1++;
mCoord[n1] = x1 + aNum[k1];
}
}
ifstream InFile("WordSearch.txt", ios::in);
for (k1 = 0; k1 <= 2; k1++)
{
getline(InFile,x1);
aField = aField + x1;
}
getline(InFile,x1);
for (k1 = 0; k1 <= 7; k1++) // There are 8 search words
getline(InFile,mWord[k1]);
InFile.close();
for (k2 = 0; k2 <= 7; k2++) // Add 8 reverse search words
{ // Instead of a reverse search, I flip the words
x1 = mWord[k2]; x2 = "";
n1 = x1.length() - 1;
for (k1 = n1; k1 >= 0; k1--)
x2 = x2 + x1.substr(k1,1);
mWord[k2+8] = x2;
}
for (k1 = 0; k1 <= 8; k1++)
mLetter[k1] = aField.substr(k1,1);
}
// Compile the coordinates for each letter of the text.
void GetCoord2()// Use search words' positions in hiding field to
{ // retrieve their coordates
int k1,k2, n1 = -1,n2 = -1, n3;
for (k2 = 0; k2 <= 2; k2++) // row
{
for (k1 = 0; k1 <= 2; k1++)
{
n1++; n2++;
nCoord[n1] = n2;
mDirec[n1] = 1; //mDirec[]: Words' spelling directions
} // 1 = row, 3 = column, 2 = forward diagonal
n1++; // 4 = backward diagonal
}
for (k2 = 0; k2 <= 2; k2++) // column
{
n2 = k2;
for (k1 = 0; k1 <= 2; k1++)
{
n1++;
nCoord[n1] = n2;
mDirec[n1] = 3;
n2 = n2 + 3;
}
n1++; // Insert a space between two lines of text
}
for (k2 = 0; k2 <= 2; k2++) // Fdiag P1; First row and left to right
{
n2 = k2;
for (k1 = 0; k1 <= k2; k1++)
{
n1++;
nCoord[n1] = n2;
mDirec[n1] = 2;
n2 = n2 + 2;
}
n1++;
}
n2 = 2;
for (k2 = 1; k2 >= 0; k2--) // Fdiag P2; Last column and top to bottom
{
n2 = n2 + 3; n3 = n2;
for (k1 = 0; k1 <= k2; k1++)
{
n1++;
nCoord[n1] = n3;
mDirec[n1] = 2;
n3 = n3 + 2;
}
n1++;
}
for (k2 = 0; k2 <= 2; k2++) // Bdiag P1; First row and left to right
{
n2 = k2;
for (k1 = k2; k1 <= 2; k1++)
{
n1++;
nCoord[n1] = n2;
mDirec[n1] = 4;
n2 = n2 + 4;
}
n1++;
}
n2 = 0;
for (k2 = 0; k2 <= 1; k2++) // Bdiag P2; First column and top to bottom
{
n2 = n2 + 3; n3 = n2;
for (k1 = k2; k1 <= 1; k1++)
{
n1++;
nCoord[n1] = n3;
mDirec[n1] = 4;
n3 = n3 + 4;
}
n1++;
} //Coordinate'elements 50
}
void GetLine3()// Change the 2-D text of the hiding field into a single
{ // string separating one unit from the other with a space
int k1,k2,n1 = -1, n2;
for (k2 = 0; k2 <= 2; k2++)
{
for (k1 = 0; k1 <= 2; k1++) // Row
{
n1++;
mLine = mLine + mLetter[n1];
}
mLine = mLine + " "; //Separate 2 lines by a space
}
for (k2 = 0; k2 <= 2; k2++) // Column
{
n1 = k2;
for (k1 = 0; k1 <= 2; k1++)
{
mLine = mLine + mLetter[n1];
n1 = n1 + 3;
}
mLine = mLine + " ";
}
for (k2 = 0; k2 <= 2; k2++) //Fdiag P1
{
n1 = k2;
for (k1 = 0; k1 <= k2; k1++)
{
mLine = mLine + mLetter[n1];
n1 = n1 + 2;
}
mLine = mLine + " ";
}
n1 = 2;
for (k2 = 0; k2 <= 1; k2++) //Fdiag P2
{
n1 = n1 + 3; n2 = n1;
for (k1 = k2; k1 <= 1; k1++)
{
mLine = mLine + mLetter[n2];
n2 = n2 + 2;
}
mLine = mLine + " ";
}
for (k2 = 0; k2 <= 2; k2++) // Bdiag P1
{
n1 = k2;
for (k1 = k2; k1 <= 2; k1++)
{
mLine = mLine + mLetter[n1];
n1 = n1 + 4;
}
mLine = mLine + " ";
}
n1 = 0;
for (k2 = 0; k2 <= 1; k2++) // Bdiag P2
{
n1 = n1 + 3; n2 = n1;
for (k1 = k2; k1 <= 1; k1++)
{
mLine = mLine + mLetter[n2];
n2 = n2 + 4;
}
mLine = mLine + " ";
} //mLine's length must match the nCoor[];
}
string Reverse5(string pWord) // Instead of words to coordates. Now
{ // it is coordates to words
int k1,n1 = -1,n2,aNum[4],aDirec;
string x1,x2;
char c1[4];
pWord.erase(2,1); //Erase the "-". e.g. AA-CC becomes AACC
pWord.copy(c1,4); // string to char and then to numbers
for (k1 = 0; k1 <= 3; k1++)
aNum[k1] = int(c1[k1]) - 65;
if (aNum[0] == aNum[2] || aNum[1] == aNum[3])
{
if (aNum[0] == aNum[2])
aDirec = 1; // Word is row oriented
else
aDirec = 3;// Word is column oriented
}
else
{
if (aNum[0] < aNum[2]) // Normal order
{
if (aNum[1] > aNum[3])
aDirec = 2; // Forward diagonal
else
aDirec = 4; // Backward diagonal
}
else //Reverse order
{
if (aNum[1] < aNum[3]) // Forward diagonal
aDirec = 2;
else
aDirec = 4; // Backward diagonal
}
}
n1 = aNum[0] * 3 + aNum[1]; // Get the positions of the words in hiding field
n2 = aNum[2] * 3 + aNum[3];
x2 = "";
if (aDirec == 1) // Row
{
if (n1 > n2) //Retrieve search words
for (k1 = n1; k1 >= n2; k1--)
x2 = x2 + mLetter[k1];
else
for (k1 = n1; k1 <= n2; k1++)
x2 = x2 + mLetter[k1];
}
else if (aDirec == 3) // Column
{
if (n1 < n2)
for (k1 = n1; k1 <= n2; k1+= 3)
x2 = x2 + mLetter[k1];
else
for (k1 = n1; k1 >= n2; k1-= 3)
x2 = x2 + mLetter[k1];
}
else if (aDirec == 2) // Forward diagonal
{
if (n1 < n2) // Words in normal order
for (k1 = n1; k1 <= n2; k1+= 2)
x2 = x2 + mLetter[k1];
else // Words in reverse order
for (k1 = n1; k1 >= n2; k1-= 2)
x2 = x2 + mLetter[k1];
}
else //Backward diagonal
{
if (n1 < n2)
for (k1 = n1; k1 <= n2; k1+= 4)
x2 = x2 + mLetter[k1];
else
for (k1 = n1; k1 >= n2; k1-= 4)
x2 = x2 + mLetter[k1];
}
return x2;
}
void FindWords4()
{
int k1,k2,p1,n1,n2,n3,aLen;
string x1,x2, aWord,aCoord,bCoord[8];
for (k1 = 0; k1 <= 15; k1++) // 0-7: Normal order and 8-15 reverse ones
{
aWord = mWord[k1];
aLen = aWord.length() - 1; n3 = k1 % 8; // convert 8 to 0 and 9 to 1 ...
p1 = mLine.find(aWord,0); //1. locate a word's position in Hiding field
if (p1 != -1) // If a search word is found
{
n1 = nCoord[p1]; // 2. retrieve the coor of the first letter
n2 = aLen * mDirec[p1] + n1; //find the coor of the last letter
x1 = mCoord[n1]; x2 = mCoord[n2];
if (k1 < 8) // 0-7: normal order and 8-15: reverse order
aCoord = x1 + "-" + x2 + " ";
else
{
aCoord = x2 + "-" + x1 + " "; //If the word is spelt in
} // reverse in the hiding field
bCoord[n3] = aCoord; // reverse the coor
}
}
cout << "Hiding Field" << endl;
cout << "a b c" << endl << "d e f"
<< endl << "g h i" << endl << endl;
cout << "Coordinates Position" << endl;
cout << "AA AB AC 0 1 2" << endl;
cout << "BA BB BC 3 4 5" << endl;
cout << "CA CB CC 6 7 8" << endl << endl;
//bCoord[1] = "AC-AB"; Unblocking this line to check for errors.
cout << " Coor Search Words" << endl;
for (k1 = 0; k1 <= 7; k1++)
cout << k1 << " " << bCoord[k1] << " " << mWord[k1] << endl;
cout << endl;
x2 = "Coordates verified. No error";
for (k1 = 0; k1 <= 7; k1++) // Find words' coornates and then reverse
{ // the process using the coornates to
x1 = Reverse5(bCoord[k1]); // retrieve the search words
if (x1 != mWord[k1])
{
x2 = "Found error/s in " + bCoord[k1] + " " + mWord[k1];
break;
}
}
cout << x2 << endl;
}
b. Word Search (An academic puzzle)
This is a copy of the previous program (the mold) plus some minor changes.
Puzzle Sorce:
www.cs.southern.edu/halterman/Courses/Winter2017/318/Assignments/
wordsearchsolver.html. (Southern Adventise University's Website)
int nCoord[1718] = {0},mDirec[1718] = {0};
string mCoord[400],mLetter[400], mLine,mWord[20];
void aMain();
void LoadPuz1();
void GetCoord2();
void GetLines3();
void FindWords4();
string Reverse5(string);
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
LoadPuz1();
GetCoord2();
GetLines3();
FindWords4();
}
void LoadPuz1() // Load the puzzle (Hiding Field and Search Words)
{
int k1,k2, n1;
string x1,x2;
string aNum[20], aField;
for (k1 = 0; k1 <= 19; k1++)
aNum[k1] = char(k1+65);
n1 = -1;
for (k2 = 0; k2 <= 19; k2++)
{
x1 = aNum[k2];
for (k1 = 0; k1 <= 19; k1++)
{
n1++;
mCoord[n1] = x1 + aNum[k1];
}
}
cout << " Hiding Field" << endl;
ifstream InFile("WordSearch.txt", ios::in);
for (k1 = 0; k1 <= 19; k1++)
{
getline(InFile,x1);
aField = aField + x1;
cout << x1 << endl;
}
cout << endl;
cout << "Coor(dinates) and Word(Search Words)" << endl;
cout << " Coor Word" << endl;
for (k1 = 0; k1 <= 9; k1++) // There are 10 search words
getline(InFile,mWord[k1]);
InFile.close();
for (k2 = 0; k2 <= 9; k2++) // Add 10 reverse search words
{
x1 = mWord[k2]; x2 = "";
n1 = x1.length() - 1;
for (k1 = n1; k1 >= 0; k1--)
x2 = x2 + x1.substr(k1,1);
mWord[k2+10] = x2;
}
for (k1 = 0; k1 <= 399; k1++)
mLetter[k1] = aField.substr(k1,1);
}
void GetCoord2()
{
int k1,k2, n1 = -1,n2 = -1, n3;
for (k2 = 0; k2 <= 19; k2++) // row
{
for (k1 = 0; k1 <= 19; k1++)
{
n1++; n2++;
nCoord[n1] = n2;
mDirec[n1] = 1;
}
n1++;
}
for (k2 = 0; k2 <= 19; k2++) // column
{
n2 = k2;
for (k1 = 0; k1 <= 19; k1++)
{
n1++;
nCoord[n1] = n2;
mDirec[n1] = 20;
n2 = n2 + 20;
}
n1++;
}
for (k2 = 0; k2 <= 19; k2++) // Fdiag P1 (Forward diagonal)
{
n2 = k2;
for (k1 = 0; k1 <= k2; k1++)
{
n1++;
nCoord[n1] = n2;
mDirec[n1] = 19;
n2 = n2 + 19;
}
n1++;
}
n2 = 19;
for (k2 = 18; k2 >= 0; k2--) // Fdiag P2
{
n2 = n2 + 20; n3 = n2;
for (k1 = 0; k1 <= k2; k1++)
{
n1++;
nCoord[n1] = n3;
mDirec[n1] = 19;
n3 = n3 + 19;
}
n1++;
}
for (k2 = 0; k2 <= 19; k2++) // Bdiag P1 (Backward diagonal)
{
n2 = k2;
for (k1 = k2; k1 <= 19; k1++)
{
n1++;
nCoord[n1] = n2;
mDirec[n1] = 21;
n2 = n2 + 21;
}
n1++;
}
n2 = 0;
for (k2 = 0; k2 <= 18; k2++)
{
n2 = n2 + 20; n3 = n2;
for (k1 = k2; k1 <= 18; k1++)
{
n1++;
nCoord[n1] = n3;
mDirec[n1] = 21;
n3 = n3 + 21;
}
n1++;
}
}
void GetLines3()
{
int k1,k2,n1 = -1, n2;
for (k2 = 0; k2 <= 19; k2++)
{
for (k1 = 0; k1 <= 19; k1++) // Row
{
n1++;
mLine = mLine + mLetter[n1];
}
mLine = mLine + " ";
}
for (k2 = 0; k2 <= 19; k2++) // Column
{
n1 = k2;
for (k1 = 0; k1 <= 19; k1++)
{
mLine = mLine + mLetter[n1];
n1 = n1 + 20;
}
mLine = mLine + " ";
}
for (k2 = 0; k2 <= 19; k2++) //Fdiag P1
{
n1 = k2;
for (k1 = 0; k1 <= k2; k1++)
{
mLine = mLine + mLetter[n1];
n1 = n1 + 19;
}
mLine = mLine + " ";
}
n1 = 19;
for (k2 = 0; k2 <= 18; k2++) //Fdiag P2
{
n1 = n1 + 20; n2 = n1;
for (k1 = k2; k1 <= 18; k1++)
{
mLine = mLine + mLetter[n2];
n2 = n2 + 19;
}
mLine = mLine + " ";
}
for (k2 = 0; k2 <= 19; k2++) // Bdiag P1
{
n1 = k2;
for (k1 = k2; k1 <= 19; k1++)
{
mLine = mLine + mLetter[n1];
n1 = n1 + 21;
}
mLine = mLine + " ";
}
n1 = 0;
for (k2 = 0; k2 <= 18; k2++) // Bdiag P2
{
n1 = n1 + 20; n2 = n1;
for (k1 = k2; k1 <= 18; k1++)
{
mLine = mLine + mLetter[n2];
n2 = n2 + 21;
}
mLine = mLine + " ";
}
}
string Reverse5(string pCoor)
{
int k1,n1 = -1,n2,aNum[4],aDirec;
string x1,x2;
char c1[4];
pCoor.erase(2,1);
pCoor.copy(c1,4);
for (k1 = 0; k1 <= 3; k1++)
aNum[k1] = int(c1[k1]) - 65;
if (aNum[0] == aNum[2] || aNum[1] == aNum[3])
{
if (aNum[0] == aNum[2])
aDirec = 1;
else
aDirec = 20;
}
else
{
if (aNum[0] < aNum[2])
{
if (aNum[1] > aNum[3])
aDirec = 19;
else
aDirec = 21;
}
else
{
if (aNum[1] < aNum[3])
aDirec = 19;
else
aDirec = 21;
}
}
n1 = aNum[0] * 20 + aNum[1];
n2 = aNum[2] * 20 + aNum[3];
x2 = "";
if (aDirec == 1)
{
if (n1 > n2)
for (k1 = n1; k1 >= n2; k1--)
x2 = x2 + mLetter[k1];
else
for (k1 = n1; k1 <= n2; k1++)
x2 = x2 + mLetter[k1];
}
else if (aDirec == 20)
{
if (n1 < n2)
for (k1 = n1; k1 <= n2; k1+= 20)
x2 = x2 + mLetter[k1];
else
for (k1 = n1; k1 >= n2; k1-= 20)
x2 = x2 + mLetter[k1];
}
else if (aDirec == 19)
{
if (n1 < n2)
for (k1 = n1; k1 <= n2; k1+= 19)
x2 = x2 + mLetter[k1];
else
for (k1 = n1; k1 >= n2; k1-= 19)
x2 = x2 + mLetter[k1];
}
else
{
if (n1 < n2)
for (k1 = n1; k1 <= n2; k1+= 21)
x2 = x2 + mLetter[k1];
else
for (k1 = n1; k1 >= n2; k1-= 21)
x2 = x2 + mLetter[k1];
}
return x2;
}
void FindWords4()
{
int k1,k2,p1,n1,n2,n3,aLen;
string x1,x2, aWord,bWord[10],aCoord, bCoord[10];
string aMess = "No error is found";
for (k1 = 0; k1 <= 19; k1++)
{
aWord = mWord[k1];
aLen = aWord.length() - 1; n3 = k1 % 10;
p1 = mLine.find(aWord,0);
if (p1 != -1)
{
n1 = nCoord[p1];
n2 = aLen * mDirec[p1] + n1;
x1 = mCoord[n1]; x2 = mCoord[n2];
if (k1 < 10)
aCoord = x1 + "-" + x2;
else
{
aCoord = x2 + "-" + x1;
}
bCoord[n3] = aCoord;
}
}
for (k1 = 0; k1 <= 9; k1++)
{
x1 = Reverse5(bCoord[k1]);
cout << k1 << " " << bCoord[k1] << " " << mWord[k1] << endl;
if (x1 != mWord[k1])
{
aMess = "Error is found.";
break;
}
}
cout << "(Coordinates: ABC... instead of 0,1,2..." << endl;
cout << "(e.g. CI-JI: Row C + Column I / Row J + Column I)" << endl << endl;
cout << aMess << endl;
}
c. Word Search (A commercial puzzle)
(A copy of the mold plus some minor changes)
Sorce of the puzzle:
https://www.puzzles-to-print.com/printable-word-search/PDFs/
summer-olympics-word-search.pdf
int nCoord[1888] = {0},mDirec[1888] = {0};
string mCoord[441],mLetter[441], mLine,mWord[80];
void aMain();
void LoadPuz1();
void GetCoord2();
void GetLine3();
void FindWords4();
string Reverse5();
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
LoadPuz1();
GetCoord2();
GetLine3();
FindWords4();
}
void LoadPuz1() // Load the puzzle (Hiding Field and Search Words)
{
int k1,k2, n1;
string x1,x2;
string aNum[21], aField;
for (k1 = 0; k1 <= 20; k1++)
aNum[k1] = char(k1+65);
n1 = -1;
for (k2 = 0; k2 <= 20; k2++)
{
x1 = aNum[k2];
for (k1 = 0; k1 <= 20; k1++)
{
n1++;
mCoord[n1] = x1 + aNum[k1];
}
}
cout << "Word Search Puzzle" << endl;
ifstream InFile("WordSearch.txt", ios::in);
for (k1 = 0; k1 <= 20; k1++)
{
getline(InFile,x1); cout << x1 << endl;
aField = aField + x1;
}
cout << endl;
for (k1 = 0; k1 <= 39; k1++) // There are 40 search words
getline(InFile,mWord[k1]);
InFile.close();
for (k2 = 0; k2 <= 39; k2++) // Add 40 reverse search words
{
x1 = mWord[k2]; x2 = "";
n1 = x1.length() - 1;
for (k1 = n1; k1 >= 0; k1--)
x2 = x2 + x1.substr(k1,1);
mWord[k2+40] = x2;
}
for (k1 = 0; k1 <= 440; k1++)
mLetter[k1] = aField.substr(k1,1);
cout << "Coor(dinates) and Word(Search Words)" << endl;
cout << " Coor Word" << endl;
}
void GetCoord2()
{
int k1,k2, n1 = -1,n2 = -1, n3;
for (k2 = 0; k2 <= 20; k2++) // row
{
for (k1 = 0; k1 <= 20; k1++)
{
n1++; n2++;
nCoord[n1] = n2;
mDirec[n1] = 1;
}
n1++;
}
for (k2 = 0; k2 <= 20; k2++) // column
{
n2 = k2;
for (k1 = 0; k1 <= 20; k1++)
{
n1++;
nCoord[n1] = n2;
mDirec[n1] = 21;
n2 = n2 + 21;
}
n1++;
}
for (k2 = 0; k2 <= 20; k2++) // Fdiag P1
{
n2 = k2;
for (k1 = 0; k1 <= k2; k1++)
{
n1++;
nCoord[n1] = n2;
mDirec[n1] = 20;
n2 = n2 + 20;
}
n1++;
}
n2 = 20;
for (k2 = 19; k2 >= 0; k2--) // Fdiag P2
{
n2 = n2 + 21; n3 = n2;
for (k1 = 0; k1 <= k2; k1++)
{
n1++;
nCoord[n1] = n3;
mDirec[n1] = 20;
n3 = n3 + 20;
}
n1++;
}
for (k2 = 0; k2 <= 20; k2++) // Bdiag P1
{
n2 = k2;
for (k1 = k2; k1 <= 20; k1++)
{
n1++;
nCoord[n1] = n2;
mDirec[n1] = 22;
n2 = n2 + 22;
}
n1++;
}
n2 = 0;
for (k2 = 0; k2 <= 19; k2++)
{
n2 = n2 + 21; n3 = n2;
for (k1 = k2; k1 <= 19; k1++)
{
n1++;
nCoord[n1] = n3;
mDirec[n1] = 22;
n3 = n3 + 22;
}
n1++;
}
}
void GetLine3()
{
int k1,k2,n1 = -1, n2;
for (k2 = 0; k2 <= 20; k2++) // Row
{
for (k1 = 0; k1 <= 20; k1++)
{
n1++;
mLine = mLine + mLetter[n1];
}
mLine = mLine + " ";
}
for (k2 = 0; k2 <= 20; k2++) // Column
{
n1 = k2;
for (k1 = 0; k1 <= 20; k1++)
{
mLine = mLine + mLetter[n1];
n1 = n1 + 21;
}
mLine = mLine + " ";
}
// mLine = "";
for (k2 = 0; k2 <= 20; k2++) //Fdiag P1
{
n1 = k2;
for (k1 = 0; k1 <= k2; k1++)
{
mLine = mLine + mLetter[n1];
n1 = n1 + 20;
}
mLine = mLine + " ";
}
n1 = 20;
for (k2 = 0; k2 <= 19; k2++) //Fdiag P2
{
n1 = n1 + 21; n2 = n1;
for (k1 = k2; k1 <= 19; k1++)
{
mLine = mLine + mLetter[n2];
n2 = n2 + 20;
}
mLine = mLine + " ";
}
for (k2 = 0; k2 <= 20; k2++) // Bdiag P1
{
n1 = k2;
for (k1 = k2; k1 <= 20; k1++)
{
mLine = mLine + mLetter[n1];
n1 = n1 + 22;
}
mLine = mLine + " ";
}
n1 = 0;
for (k2 = 0; k2 <= 19; k2++) // Bdiag P2
{
n1 = n1 + 21; n2 = n1;
for (k1 = k2; k1 <= 19; k1++)
{
mLine = mLine + mLetter[n2];
n2 = n2 + 22;
}
mLine = mLine + " ";
}
}
string Reverse5(string pWord)
{
int k1,n1 = -1,n2,aNum[4],aDirec;
string x1,x2;
char c1[4];
pWord.erase(2,1);
pWord.copy(c1,4);
for (k1 = 0; k1 <= 3; k1++)
aNum[k1] = int(c1[k1]) - 65;
if (aNum[0] == aNum[2] || aNum[1] == aNum[3])
{
if (aNum[0] == aNum[2]) //Row
aDirec = 1;
else
aDirec = 21; //Column
}
else
{
if (aNum[0] < aNum[2])
{
if (aNum[1] > aNum[3])
aDirec = 20; //Forward Diagonal
else
aDirec = 22; //Backward Diagonal
}
else
{
if (aNum[1] < aNum[3]) //Forward Diagonal(reverse order)
aDirec = 20;
else
aDirec = 22; //Backward Diagonal(reverse order)
}
}
n1 = aNum[0] * 21 + aNum[1];
n2 = aNum[2] * 21 + aNum[3];
x2 = "";
if (aDirec == 1)
{
if (n1 > n2)
for (k1 = n1; k1 >= n2; k1--)
x2 = x2 + mLetter[k1];
else
for (k1 = n1; k1 <= n2; k1++)
x2 = x2 + mLetter[k1];
}
else if (aDirec == 21)
{
if (n1 < n2)
for (k1 = n1; k1 <= n2; k1+= 21)
x2 = x2 + mLetter[k1];
else
for (k1 = n1; k1 >= n2; k1-= 21)
x2 = x2 + mLetter[k1];
}
else if (aDirec == 20)
{
if (n1 < n2)
for (k1 = n1; k1 <= n2; k1+= 20)
x2 = x2 + mLetter[k1];
else
for (k1 = n1; k1 >= n2; k1-= 20)
x2 = x2 + mLetter[k1];
}
else
{
if (n1 < n2)
for (k1 = n1; k1 <= n2; k1+= 22)
x2 = x2 + mLetter[k1];
else
for (k1 = n1; k1 >= n2; k1-= 22)
x2 = x2 + mLetter[k1];
}
return x2;
}
void FindWords4()
{
int k1,k2,p1,n1,n2,n3,aLen;
string x1,x2, aWord,bWord[40],aCoord, bCoord[40];
string aMess = "No error is found";
for (k1 = 0; k1 <= 79; k1++) //0-39: normal order; 40-79: reverse order
{
aWord = mWord[k1];
aLen = aWord.length() - 1; n3 = k1 % 40;
p1 = mLine.find(aWord,0);
if (p1 != -1)
{
n1 = nCoord[p1];
n2 = aLen * mDirec[p1] + n1;
x1 = mCoord[n1]; x2 = mCoord[n2];
if (k1 < 40)
aCoord = x1 + "-" + x2;
else
{
aCoord = x2 + "-" + x1;
}
bCoord[n3] = aCoord;
}
}
ofstream OutFile("FindWord39.txt",ios::out);
for (k1 = 0; k1 <= 39; k1++)
{
cout << k1 << " " << bCoord[k1] << " " << mWord[k1] << endl;
OutFile << k1 << " " << bCoord[k1] << " " << mWord[k1] << endl;
}
OutFile.close();
cout << endl;
cout << "*The first 2-letter < the last 2-letter, words are spelt normally" << endl;
cout << " else words are spelt reversely in Hiding Field" << endl;
cout << " e.g. wrestling is spelt reversely becase OG > GG" << endl;
for (k1 = 0; k1 <= 39; k1++)
{
x1 = Reverse5(bCoord[k1]);
if (x1 != mWord[k1])
{
aMess = "Error is found.";
break;
}
}
cout << aMess << endl;
}
***** 3
Dealer-assisted Poker Program
Automating card shuffling, 0-3 card replacement and determination on
which hand wins, ties or loses to another hand.
This program extensively uses numerical patterns to pile up all 2 million
plus hands, rates them and readies them for 0-3 card replacement. It then
structures those hands for a dictionary-styped rating retrieval.
Program Overview
1. Data Representation
Use consecutive 52 ASCII characters (0 to c) and their integer equivalence
(they are easily convertible to each other) to represent 52 cards (No extra
cards are allowed).
Use 0 to 8 (d,e,f ... l) to represent hand types (high cards, one pair, two
pairs ... flush straight)
List A (mNum[n]) List B List C
Face and suite 52 cards' ID Cross-Reference Index to Cards' ID
(Col. are suite Rows are face)
0 = J W 0 13 26 39 0 1 2 3
1 > K X 1 14 27 40 4 5 6 7
2 ? L Y 2 15 28 41 8 9 10 11
3 @ M Z 3 16 29 42 12 13 14 15
4 A N [ 4 17 30 43 16 17 18 19
5 B O \ 5 18 31 44 20 21 22 23
6 C P ] 6 19 32 45 24 25 26 27
7 D Q ^ 7 20 33 46 28 29 30 31
8 E R _ 8 21 34 47 32 33 34 35
9 F S ` 9 22 35 48 36 37 38 39
: G T a 10 23 36 49 40 41 42 43
; H U b 11 24 37 50 44 45 46 47
< I V c 12 25 38 51 48 49 50 51
The suite order: Heart, Diamond, Club, Spade (in column)
The IDs are stored in string mNum[52].
When opening a box of brand-new playing cards, you see the same order
listed above titled 52 cards'ID.
Numerical Patterns-based coding works as follows
a. To get all 13 quads (for four of kind hand)
Line up 52 cards row by row:
n1 = -13;
for k1 = 0; k1 <= 50
n1 = (n1 + 13) % 51
x1 = x1 + mNum[n1]
x1 = x1 + "c"
n1 = -4;
for k1 = 0 to 12
n1 = n1 + 4
quad[k1] = x1.substr(n1,4)
b. To get all 78 pairs and 52 triples
Set up starter index[n] (row 1) for both pair and triple
Index2[] = {0,13,0,26,0,39,13,26,13,39,26,39};
Index3[] = {0,13,26,0,13,39,0,26,39,13,26,39};
for k2 = 0;k2 <= 12
for k1 = 0; k1 <= 11
n1 = k2 + Index2[k1]; x1 = x1 + mNum[n1];
n1 = k2 + Index3[k1]; x2 = x2 + mNum[n1];
n1 = -2;
for k1 = 0; k1 <= 77
n1 = n1 + 2;
pair[k1] = x1.substr(n1,2)
n1 = -3;
for k1 = 0; k1 <= 51
n1 = n1 + 3;
triple[k1] = x2.substr(n1,3)
c. To get all flush hands, make hands from Column 1 and then
add 13,26,39 to the hands. You get all flush hands.
To get all straight hands. You first make hands from the first 5 rows
Then add number 1-8 to the hands. You get all straight hands.
2. Make a database (in the form of structured text file)
a. Using 0-8 functions to pile up all 2,598,960 hands plus their attributes
e.g. the entity of the database: 0123Bd=53210B321 is divided into 3 parts.
0123B d=5321 0B321
0123B: Ace of Heart, Two of Heart, Three of Heart and Four of Heart,
Five of Diamond
d=5321: Hand type d or 0 point (see Hand Rating Chart below).
Face value =5321 is 13,5,3,2,1 (Ace is considered biggest card here)
b. 0B321: Card-replacement order.
The program decides the number of card to be replaced according to
the hand type:
Point 4 - 8: 5 (keep 0B321 and add 0 card)
Point 3: 3 (keep 0B3 and add 2 cards)
Point 2: 4 (keep 0B32 and add 1 card)
Point 1 & 0: 2 (keep 0B and add 3 cards)
Here I pretend 0B321 is any type of hand
How to get replacement members?
Set up cross-reference index:
string aType = "defghijkl"; (from high card to straight flush)
int aLen[] = {2,2,4,3,5,5,5,5,5};
bType = "d";
n1 = aType.find(bType,0); n1 = 2; (keep 2 cards)
n2 = 5 - n1; n2 = 3; (add 3 cards)
available cards = "0B321"
if bType = "l" then n1 = 5; n2 = 0; (No replacement)
A simple way of 52-card shuffling
string x1,aCard, bCard;
for (k1 = 0; k1 <= 51; k1++)
{
x1 = char(k1 + 48);
aCard = aCard + x1;
for (k1 = 52; k1 >= 1; k1--)
{
n1 = rand() % k1;
bCard = bCard + aCard.substr(n1,1);
aCard.erase(n1,1);
}
bCard is the shuffled 52 cards.
c. Do within-hand sorting
d. Structure 2,598,960 into an array of 2548 by 1020
(2548 lines and 1020 hands per line)
array[n].substr(0,5): 5 card IDs, array[n].substr(5,1): hand type,
array[n].substr(5,6): hand-comparable value,
array[n].substr(11,5): replacement available cards
e. Make a header array of the first 5 characters of each line
and add an ender "xxxxx" as array[2548].
f. Now you input a hand to a retrieval function to get the data needed
to perform each step of game playing.
g. This is a retrieval simila to looking up a word in a dictionary:
for (k1 = 0; k1 <= 2548; k1++)
if (Hand < Header[k1]) break;
x1 = array[k1-1];
n1 = x1.find(Hand,0);
retrieval = x1.substr(n1,11);
Hand Rating
Name code Pt Point Count
Straight Flush..... l 8 40
Pour of a Kind..... k 7 624
Full House......... j 6 3,744
Flush.............. i 5 5,108
Straight........... h 4 10,200
Three of a Kind.... g 3 54,912
Two Pairs.......... f 2 123,552
One Pair........... e 1 1,098,240
High Cards......... d 0 1,302,540
Total 2,598,960
Ace can be the strongest or the weakest card depending on hand type.
How does point count come from?
Straight Flush: 10 hands per column * 4 columns; 10 * 4 = 40 hands
Four of a Kind: 13 rows of 4-card * 48 not-same-face-valued cards; 13 * 48 = 624
Full House: Per row, there are 4 cards which have the same face value: a,b,c,d.
a,b,c,d permutate to 4 triples and 6 pairs.
Triple: abc,abd,acd,bcd; 13 rows * 4 = 52
Pair: ab,ac,ad,bc,bd,cd; 13 rows * 6 = 78
Each triple picks up 72 pairs: 52 * 72 = 3744
How do you make a triple picks up only the pairs with different
face value. You make a merry-go-arround index for 78 pairs.
for k1 = 0 to 78
Index[k1] = Pair[k1];
Index[k1+ 78] = Pair[k1];
n1 = -1;
for k2 = 0 to 3
x = triple[k2]
for k1 = 6 to 78 (each triple picks up 72 pairs)
n1++;
Hand = x1 + Index[n1]
So the index[n] serves as an endless conveyor belt until job done.
Flush: Each column of 13 cards permutate 1277 hands. 1277 * 4 = 5,108
Straight: Each column (13 cards) permutates 9 groups + extra group (0,9,10,11,12)
Each group permutates 1020 hands. 10 groups * 1020 = 10,200
Three kind:52 cards permutate 52 triples and 1248 not-same-face-valued 2-card sets
Each triple picks 1056 2-card sets. 52 * 1056 = 54912
Two Pairs: 52 cards permutate 78 pairs. For self-combination, 78 pairs generate
2808 2-pair sets. Each 2-pair set picks up 44 cards.
2808 * 44 = 123,552
One Pair: 52 cards permutate 78 pairs and 18304 3-card sets.
78 (pairs) * 18304 (3-card sets) = 1,098,240
High Card: 52 cards are organized into 13 groups by the cards' face value.
13 groups are combined into 1277 5-card-sets.
Each group sub-set-combines 1020 hands. 1277 * 1020 = 1,302,540 hands
Each 1020 hands have the same face value. The value is used as the
the within-hand-type comparison (rating).
e.g. first group: 01235. Its sub-group combination can be explained
as follows:
0a,0b,0c,0d
1a,1b,1c,1d
2a,2b,2c,2d
3a,3b,3c,3d
5a,5b,5c,5d
The first hand: 0a,1a,2a,3a,5b. The last: 0d,1d,2d,3d,5c
Notice: the hands, its 5 cards are from the same column, are Hand Flush.
How do you filter out bad hands. You set up a counter. When the hand
counter n1 % 341 == 0, it is the bad hand. You skip over it.
Permutation of 4 by 5: pow(4,5) = 1024 - 4 = 1020
Sub-program 1 (Poker Series) Compiling this program takes more than 30 minutes.
Assembling a hand list (2,598,960 hands) to pile up a database in text form
Using both string and int types to represent 52 cards
e.g. King of Spade is c in string and 51 in int Data type
void aMain();
void SetUp();
void Point0();void Point1();void Point2();
void Point3();void Point4();void Point5();
void Point6();void Point7();void Point8();
void Replace9();//Replace 0-3 cards according to hand types
void Sort10(); //Put each 5 cards in ascending order and rating in descending
void LineUp11(); //Put 2 million plus hands in a structure of 2548 by 1020
void QuickSort(int,int); //Sort 2 million plus hands by ascending order.
string mNum[52], nNum,mFace[52],mRow[100],mMove[1176];
string mTwo[156], mThree[52];
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
SetUp();
Point0(); Point1(); Point2();
Point3(); Point4(); Point5();
Point6(); Point7(); Point8();
Replace9();
Sort10();
LineUp11();
}
void SetUp()
{
int k1,k2,n1 = -1,n2 = -13,aTwo[] = {0,13,0,26,0,39,13,26,13,39,26,39};
int aThree[] = {0,13,26,0,13,39,0,26,39,13,26,39}; // First row's 2-cards pairs
string x1,x2; // First row's 3-cards triples
for (k1 = 0; k1 <= 51; k1++)
{
x1 = char(k1 + 48);
mNum[k1] = x1; //mNum[n] represens 52 cards
nNum = nNum + x1; // One string for 52 cards, for card-shuffling
}
for (k1 = 0; k1 <= 51; k1++)
{
n1 = k1 % 13; mFace[k1] = mNum[n1];//52 cards' face value
n2 = (n2 + 13) % 51; mRow[k1] = mNum[n2]; //Cross-reference to mNum[n]
}
mRow[51] = "c";
for (k1 = 0;k1 <= 47; k1++)
mRow[k1+52] = mRow[k1]; //Set up merry-go-around index
x1 = ""; x2 = "";
for (k2 = 0;k2 <= 12; k2++)// Add 1 - 12 to first row's pairs and triple.
{ //Permutate 52 cards to get 52 triples and 78 pairs
for (k1 = 0; k1 <= 11; k1++)
{
n1 = k2 + aTwo[k1]; x1 = x1 + mNum[n1];
n1 = k2 + aThree[k1]; x2 = x2 + mNum[n1];// cards in integer
} // change to cards in string
}
x1 = x1 + x1;
n1 = -2;
for (k1 = 0; k1 <= 155; k1++)
{
n1 = n1 + 2; mTwo[k1] = x1.substr(n1,2); //Set up merry-go-around index
}
n1 = -3;
for (k1 = 0; k1 <= 51; k1++)
{
n1 = n1 + 3; mThree[k1] = x2.substr(n1,3);
}
}
void Point0() //High Card: 1,302,540
{
int k1,k2,k3,k4,k5, k6,n1 = -1,n2, n3, n4,n5,n6,n7 = -1,aGroup[6385];
string x1,x2,x3,x4,x5,aSort[52],aTail[6385],bTail,aHand;
bool aStop;
char c1[6385];
for (k5 = 0; k5 <= 7; k5++)//0-12 rows permutate 1278 5-card groups
{ //k5 0-7 start with a single bad hand (straight flush)
x5 = mNum[k5]; aStop = false;//01234,12345 ... 7,8,9, 10,11. aStop:a filter
for (k4 = k5 + 1; k4 <= 9; k4++)
{
x4 = x5 + mNum[k4];
for (k3 = k4 + 1; k3 <= 10; k3++)
{
x3 = x4 + mNum[k3];
for (k2 = k3 + 1; k2 <= 11; k2++)
{
x2 = x3 + mNum[k2];
for (k1 = k2 + 1; k1 <= 12; k1++)
{
if (aStop == true) //Filter out straight flush hand
{
n1++;
x1 = x1 + x2 + mNum[k1];
}
aStop = true;
}
}
}
}
}
//n1 = 1277 * 5 = 6384
n1 = x1.find("09:;<",0); // "09:;<" is a straight flush hand
x1.erase(n1,5);
x1.copy(c1,6385); // data type conversion. string to char to integer - 48
for (k1 = 0; k1 <= 6384; k1++)
aGroup[k1] = (int(c1[k1]) - 48) * 4;//01234 = 0,4,8,12,16. 4 row per cards
for (k2 = 0;k2 <= 6380; k2+= 5)
{
x2 = x1.substr(k2, 5);
x3 = "";
for (k1 = 4; k1 >= 0; k1--) // a 5-card hand is in ascending order but
x3 = x3 + x2.substr(k1,1);//rating is in descending order.12345 = 54321
if (k2 < 2465) // Hands 0 - 2464 have an Ace and is counted as 13 not 0
aTail[k2] = "d=" + x3.substr(0,4);
else
aTail[k2] = "d" + x3; //aTail[n] is used as rating
}
// Hand groups (1278) permutate into 1,302,540 hands
ofstream OutFile("1302539.txt",ios::out); // Use .txt as a C++'s memory extension
for (k6 = 0; k6 <= 6380; k6+= 5) // Array size limit: 250,000
{
n5 = aGroup[k6]; n4 = aGroup[k6+1];
n3 = aGroup[k6+2]; n2 = aGroup[k6+3]; n1 = aGroup[k6+4];
bTail = aTail[k6];//each 1278 hands have the same rating (5 cards' face value)
n6 = -1;
for (k5 = n5; k5 <= n5 + 3; k5++)
{
x5 = mRow[k5];
for (k4 = n4; k4 <= n4 + 3; k4++)
{
x4 = x5 + mRow[k4];
for (k3 = n3; k3 <= n3 + 3; k3++)
{
x3 = x4 + mRow[k3];
for (k2 = n2; k2 <= n2 + 3; k2++)
{
x2 = x3 + mRow[k2];
for (k1 = n1; k1 <= n1 + 3; k1++)
{
n6++;
if (n6 != 0 && n6 % 341 != 0)
{ //#341 and its multiples: bad hands
n7++;
x1 = x2 + mRow[k1] + bTail;
OutFile << x1 << endl;
}
}
}
}
}
}
}
OutFile.close(); // n7 must be 1302539
ifstream InFile("1302539.txt",ios::in); //2598960.txt picks up hands
ofstream appFile("2598960.txt", ios::app); //type by type
for (k3 = 0; k3 <= 1302539; k3++) //Within-hand sorting and saving
{
InFile >> aHand;
x1 = aHand.substr(0,5); x2 = aHand.substr(5,6);
for (k2 = 0; k2 <= 4; k2++)
{
x3 = x1.substr(k2,1);
for (k1 = 0; k1 <= 51; k1++)
{
if (x3 == mNum[k1])
{
aSort[k1] = x3;
goto aSkip;
}
}
aSkip: k1 = 0;
}
aHand = "";
for (k2 = 0; k2 <= 51; k2++)
{
aHand = aHand + aSort[k2];
aSort[k2] = "";
}
aHand = aHand + x2;
appFile << aHand << endl;
}
appFile.close();
InFile.close();
}
void Point1() //One pair: 1,098,240. One pair + 3 individual cards,none of
{//the 3 has the same face value with that of the pair and with each other
int k1,k2,k3,k4, n1 = -1, n2,n3, n4 = -1, aGroup[858];
string aOne[18304],bOne[18304],cOne[18304],bGroup[858],cGroup[858];
string x1,x2,x3,aHand,aFace,bFace,aSort[52],aRate;
char c1[858];
for (k3 = 0; k3 <= 10; k3++) // Pile up 3 dissociated card sets
{
x3 = mNum[k3];
for (k2 = k3 + 1; k2<= 11; k2++)
{
x2 = x3 + mNum[k2];
for (k1 = k2 + 1; k1 <= 12; k1++)
{
n1++;
x1 = x2 + mNum[k1];
aFace = aFace + x1;
bFace = x1.substr(2,1) + x1.substr(1,1) + x1.substr(0,1);
if (n1 < 66) bFace = "=" + x1.substr(2,1) + x1.substr(1,1);
aRate = aRate + bFace;
}
}
}
aFace.copy(c1,858);
for (k1 = 0; k1 <= 857; k1++)
aGroup[k1] = (int(c1[k1]) - 48) * 4;
n1 = -3;
for (k1 = 0; k1 <= 855; k1+= 3) // 858
{
n1 = n1 + 3;
bGroup[k1] = aFace.substr(n1,3);
cGroup[k1] = aRate.substr(n1,3);
}
n4 = -1;
for (k4 = 0; k4 <= 855; k4+= 3) //18303
{
n3 = aGroup[k4]; n2 = aGroup[k4 + 1];
n1 = aGroup[k4 + 2];
aFace = bGroup[k4]; bFace = cGroup[k4];
for (k3 = n3; k3 <= n3 + 3; k3++)
{
x3 = mRow[k3];
for (k2 = n2; k2 <= n2 + 3; k2++)
{
x2 = x3 + mRow[k2];
for (k1 = n1; k1 <= n1 + 3; k1++)
{
n4++;
x1 = x2 + mRow[k1];
aOne[n4] = x1;
bOne[n4] = aFace;
cOne[n4] = bFace;
}
}
}
}
n2 = -1;
ofstream OutFile("1098240.txt", ios::out); //Temporary file
for (k4 = 0; k4 <= 77; k4++)
{
x1 = mTwo[k4];
n1 = k4 / 6; aFace = mNum[n1];
if (n1 == 0)
bFace = "=";
else
bFace = aFace;
for (k3 = 0; k3 <= 18303; k3++)
{
if (bOne[k3].find(aFace,0) == -1)
{
n2++;
x2 = x1 + aOne[k3] + "e" + bFace + cOne[k3] + "0";
OutFile << x2 << endl;
}
}
}
OutFile.close();
ifstream InFile("1098240.txt", ios::in);
ofstream appFile("2598960.txt", ios::app);
for (k3 = 0; k3 <= 1098239; k3++)
{
InFile >> x2;
x1 = x2.substr(0,5); x2 = x2.substr(5,11);
for (k2 = 0; k2 <= 4; k2++)
{
x3 = x1.substr(k2,1);
for (k1 = 0; k1 <= 51; k1++)
{
if (x3 == mNum[k1])
{
aSort[k1] = x3;
goto aSkip;
}
}
aSkip: k1 = 0;
}
aHand = "";
for (k2 = 0; k2 <= 51; k2++)
{
aHand = aHand + aSort[k2];
aSort[k2] = "";
}
aHand = aHand + x2;
appFile << aHand << endl;
}
InFile.close();
appFile.close();
}
void Point2() //2 pairs: 123,552
{
int k1,k2, k3, k4,n1,n2,n3 = -1,aStart, bStart;
string x1,x2, x3,aPair2[2808], bPair2[2808],cPair2[2808], aHead,bHead, aTail;
string aFace,aSort[52],aHand;
//72 pairs's self combination: e.g. a,b,c,d,e
// Combination yield: ab,ac,ad,ae / bc,bd,be / cd,ce/ de
// x1 = "abcde";
// for k2 = 0 to 3
// x2 = x1.substr(k2,1);
// for (k1 = k2 + 1; k1 <= 4; k1++)
// x3 = x2 + x1.substr(k1,1);
for (k3 = 0; k3 <= 72; k3+= 6)
{
aStart = k3; bStart = aStart + 6; //Each row group has 6 pairs
n2 = k3 / 6; aFace = mNum[n2]; //Pair 0-5 picks 6 - 77
for (k2 = aStart; k2 <= aStart + 5; k2++) //Pair 6-11 picks 12 - 77 etc.
{
x2 = mTwo[k2];
for (k1 = bStart; k1 <= 77; k1++)
{
n3++;
x1 = x2 + mTwo[k1];
aPair2[n3] = x1; //2-pair (4 cards' IDs)
n1 = k1 / 6;
bPair2[n3] = aFace + mNum[n1]; //2-pair (4 cards' face value)
if (n3 < 432) // 78 pairs combine to 2808 2-pair sets.
cPair2[n3] = "=" + mNum[n1]; //0-431 have an Ace
else
cPair2[n3] = mNum[n1] + aFace;
}
}
}
ofstream appFile("2598960.txt", ios::app);
n1 = -1;
for (k4 = 0; k4 <= 2807; k4++)//Each 2-pair set picks up 44 cards to be 5-card hands
{ //aPair2[n]: 4 Card CDs e.g. "JWKX'
x1 = aPair2[k4]; //bPair2[n]: 2 characters for 4 cards' face value
x2 = bPair2[k4]; x3 = cPair2[k4]; // 0 is zero. It is used as a filter
for (k3 = 0; k3 <= 51; k3++) //cPair2[n]: same as bPairs[n] but
{ // but 0 is = (13), used rating
if (x2.find(mFace[k3],0) == -1)//Only cards with different face values
{ //x2 is a filter
n1++;
aHead = x1 + mNum[k3];
aTail = "f" + x3 + mFace[k3] + "00"; //x3 is a rating
for (k2 = 0; k2 <= 4; k2++)
{
bHead = aHead.substr(k2,1);
for (k1 = 0; k1 <= 51; k1++)
{
if (bHead == mNum[k1])
{
aSort[k1] = bHead;
goto aSkip;
}
}
aSkip: k1 = 0;
}
aHead = "";
for (k2 = 0; k2 <= 51; k2++)
{
aHead = aHead + aSort[k2];
aSort[k2] = "";
}
aHand = aHead + aTail;
appFile << aHand << endl;
}
}
}
appFile.close();
}
void Point3() // 3 kind: 54912
{ // If a player gets a triple, no one else has the triple with the same face value.
int k1,k2, k3,n1, n2, n3 = -1, aStart, bStart; //So a triple's face value is used for
string x1,x2,x3,aOne[1248], bOne[1248],aHand[54912],aTail,aSort[52];
// within type's comparison
for (k3 = 0; k3 <= 44; k3+= 4) //Combine 1248 3-card sets from 52 cards
{
aStart = k3; bStart = aStart + 4;
n1 = k3 / 4; x1 = mNum[n1];
for (k2 = aStart; k2 <= aStart + 3; k2++)
{
x2 = mRow[k2];
for (k1 = bStart; k1 <= 51;k1++)
{
n2 = k1 / 4;
n3++;
aOne[n3] = x2 + mRow[k1];
bOne[n3] = x1 + mNum[n2]; //the face value of 1248 3-card sets
} //used as filters.
}
}
n2 = -1;
for (k2 = 0; k2 <= 51; k2++) // Each triple picks up 1056 2-card sets
{
x1 = mThree[k2];
n1 = k2 / 4; x2 = mNum[n1]; //Triples 0-3: face value = 0, 4-7: 2 e.t.c.
if (n1 == 0)
x3 = "="; // = is 13
else
x3 = x2;
for (k1 = 0; k1 <= 1247; k1++) // Triples pick ups only those 2-card sets
{ // which have different face value with the triples
if (bOne[k1].find(x2,0) == -1) // Filtering out bad 2-card sets
{
n2++;
aHand[n2] = x1 + aOne[k1] + "g" + x3;
}
}
}
ofstream appFile("2598960.txt", ios::app);
for (k3 = 0; k3 <= 54911; k3++) // Within hand sorting
{
x1 = aHand[k3]; aTail = x1.substr(5,2);
for (k2 = 0; k2 <= 4; k2++)
{
x2 = x1.substr(k2,1);
for (k1 = 0; k1 <= 51; k1++)
{
if (x2 == mNum[k1])
{
aSort[k1] = x2;
goto aSkip;
}
}
aSkip: k1 = 0;
}
x1 = "";
for (k2 = 0; k2 <= 51; k2++)
{
x1 = x1 + aSort[k2];
aSort[k2] = "";
}
x3 = x1 + aTail + "0000"; //Pad 4 zeros to form 11 in length
appFile << x3 << endl; // 5 characters for hand and 6 for rating
}
}
void Point4() // Straight: 10200;
{
int k1,k2, k3,k4,k5,n1 = -1, n2 = -1, n3,aCard[51000];
string x1,x2, x3,x4,x5, aSort[52],aHand;
string aRate[] = {"h0","h=","h1","h2","h3","h4","h5","h6","h7","h8"};
char c1[5100]; // Of the 5 cards of a hand, one with the smallest face value
// is used for within typed hands comparison
//There are 10 row groups. 1020 hands per group. That means 1020 hands
//have the same rating.
for (k5 = 0; k5 <= 3; k5++) // Permutate 1020 hands from first 5 rows. rating = h0
{
x5 = mRow[k5];
for (k4 = 4; k4 <= 7; k4++)
{
x4 = x5 + mRow[k4];
for (k3 = 8; k3 <= 11; k3++)
{
x3 = x4 + mRow[k3];
for (k2 = 12; k2 <= 15; k2++)
{
x2 = x3 + mRow[k2];
for (k1 = 16; k1 <= 19; k1++)
{
n1++;
if (n1 % 341 != 0)// There are 4 straight flush ahands
x1 = x1 + x2 + mRow[k1]; // skip over them
} } } } }
x1.copy(c1,5100); // First row group: 0,1,2,3,4 and the second: 0,9,10,11,12
for (k1 = 0; k1 <= 5099; k1++)// Get second 1020 hands for second 5-rows: rating: h=
{
n2 = k1 + 5100;
aCard[k1] = int(c1[k1]) - 48;
aCard[n2] = aCard[k1];
if (k1 % 5 != 0) aCard[n2] = aCard[k1] + 8; // Grouping: 09:;<
}
for (k2 = 1; k2 <= 8;k2++) // Now complete all 10 5-row hands
{
for (k1 = 0; k1 <= 5099; k1++)
{
n2++;
aCard[n2] = aCard[k1] + k2;
}
}
ofstream appFile("2598960.txt", ios::app);
n1 = -1; n3 = 0;
for (k2 = 0; k2 <= 10199; k2++) // Within hand sorting and add ratings
{
n3 = k2 / 1020; x2 = aRate[n3] + "0000";
for (k1 = 0; k1 <= 4; k1++)
{
n1++;
n2 = aCard[n1];
aSort[n2] = mNum[n2];
}
x1 = "";
for (k1 = 0; k1 <= 51; k1++)
{
x1 = x1 + aSort[k1];
aSort[k1] = "";
}
aHand = x1 + x2;
appFile << aHand << endl;
}
appFile.close();
}
void Point5() // Flush: 5108
{
int k1,k2, k3,k4,k5,n1, n2,bCard[25540];
string x1,x2, x3,x4,x5, aCard, aFace[1277], aHand;
bool aStop;
char c1[6385];
for (k5 = 0; k5 <= 7; k5++) // Permutate 1277 hands from 13 cards in Column 1.
{ //Each k5 starts with a bad hand (e.g. 01234, to 789,10,11)
x5 = mNum[k5]; aStop = false; //aStop skips over all 8 bands
for (k4 = k5 + 1; k4 <= 9; k4++)
{
x4 = x5 + mNum[k4];
for (k3 = k4 + 1; k3 <= 10; k3++)
{
x3 = x4 + mNum[k3];
for (k2 = k3 + 1; k2 <= 11; k2++)
{
x2 = x3 + mNum[k2];
for (k1 = k2 + 1; k1 <= 12; k1++)
{
x1 = x2 + mNum[k1];
if (aStop == true)
aCard = aCard + x1;
aStop = true;
}
}
}
}
}
n1 = aCard.find("09:;<",0); //"09:;<" (0,9,10,11,12) is straight flush. Take it out.
aCard.erase(n1,5);
n1 = -5;
for (k2 = 0; k2 <= 1276; k2++) // Reverse face value in hands to use as a rating
{ // 35678 becomes 87653. e.g. 35678 is smaller than 12349
n1 = n1 + 5;
x1 = aCard.substr(n1,5); x2 = "";
for (k1 = 4; k1>= 0; k1--)
{
x2 = x2 + x1.substr(k1,1);
}
aFace[k2] = x2;
if (k2 < 493) //Hand count 0-492 have an Ace. 0 become 13 (=)
aFace[k2] = "i=" + x2.substr(0,4);
else
aFace[k2] = "i" + x2;
}
aCard.copy(c1,6385); //Change hands from string to integer
x1 = "";
for (k1 = 0; k1 <= 6384; k1++)
{
n1 = int(c1[k1]) - 48;
bCard[k1] = n1;
x1 = x1 + mNum[n1];
}
for (k2 = 13; k2 <= 39; k2+= 13) //Add 13, you get second column hands, then 26 and 39
{
for (k1 = 0; k1 <= 6384; k1++)
{
n1 = k2 + bCard[k1];
x1 = x1 + mNum[n1];
}
}
ofstream appFile("2598960.txt", ios::app);
n1 = -5;
for (k1 = 0;k1 <= 5107; k1++)
{
n1 = n1 + 5; n2 = k1 % 1277;
aHand = x1.substr(n1,5) + aFace[n2];
appFile << aHand << endl;
}
appFile.close();
}
void Point6() // Full House: 3744
{
int k1,k2, k3,n1, n2, n3;
string x1,x2, aCard[18720],aSort[52],aHand[3744];
n1 = -4; n2 = 0;
x2 = "";
for (k3 = 0; k3 <= 12; k3++)
{
n1 = n1 + 4; n2 = n2 + 6; // a,b,c,d permutate 4 triples and 6 pairs
for (k2 = n1; k2 <= n1 + 3; k2++) //Each triple picks up 72 pairs
{ //in merry-go-around way.
x1 = mThree[k2];
for (k1 = n2; k1 <= n2 + 71; k1++)
x2 = x2 + x1 + mTwo[k1];
}
}
// Explanation: abc combine 1234
// aArray[] = abc; bArray[] = 12341234
// n1 = -1; // Merry-go-around counter
// for k2 = 0 to 2
// x2 = aAray[k2]
// for k1 = 0 to 3
// n1++
// x1 = x2 + bArray[n1]
n1 = x2.length();
for (k1 = 0; k1 < n1; k1++)
aCard[k1] = x2.substr(k1,1);
n1 = -1;
for (k3 = 0; k3 <= 3743; k3++) //If one player has a triple, no one else
{ //has a triple with the same face value
x1 = "";// So a triple's face value is within-type strength determinator
for (k2 = 0; k2 <= 4; k2++) //Sorting the 5 cards within a hand
{
n1++;
x2 = aCard[n1];
for (k1 = 0; k1 <= 51; k1++)
{
if (x2 == mNum[k1])
{
aSort[k1] = x2; goto aSkip;
}
}
aSkip: k1 = 0;
}
for (k2 = 0; k2 <= 51; k2++)
{
x1 = x1 + aSort[k2]; aSort[k2] = "";
}
aHand[k3] = x1;
}
// Explanation: sorting
// x1 = 75981
// sort[7] = 7; sort[5] = 5; sort[9] = 9; sort[8] = 8; sort[1] = 1;
// for k1 = 0 to 51
// x2 = x2 + sort[k1]
// x2 = 15789
ofstream appFile("2598960.txt", ios::app);
n1 = -1; mNum[0] = "="; // = is 13, the highest face value
for (k1 = 0; k1 <= 3743; k1++)
{
if (k1 % 288 == 0) n1++; //face value 0 (Ace) is counted as 13
x1 = "j" + mNum[n1]; // hand 0 - 288: face 0 and 289 + 288 face 1 etc.
x2 = aHand[k1] + x1 + "0000";
appFile << x2 << endl;
}
appFile.close();
mNum[0] = "0"; //We switched 0 to 13. Now we switches 13 back to 0;
}
void Point7() // Four Kind; 624
{
int k1,k2, k3,n1 = -4, n2;
string x1,x2, x3,x4,aFace,bFace,aSort[52],aHand;
for (k1 = 0; k1 <= 51; k1++)
x1 = x1 + mRow[k1]; //mRow[51]: 52 cards in row by row order
for (k2 = 0; k2 <= 12; k2++) // there are 13 Four-Kind combinations and
{ //each picks up 48 single cards 13 * 48 = 624
n1 = n1 + 4;
x2 = x1.substr(n1,4); aFace = mFace[k2];
if (k2 == 0)
bFace = "="; //In all of these hands, Ace is counted as 13
else
bFace = aFace;
for (k1 = 0; k1 <= 51; k1++)
{
if (aFace != mFace[k1])
{
x3 = x3 + x2 + mNum[k1] + "k" + bFace;
} // for within -typed hand comparion, only the face
} // value of the 4-kind cards is needed. A string is 7 in length
} // 0-4: 5 cards' ID, 5: hand type; 6: Sub-type rating.
ofstream appFile("2598960.txt", ios::app);
n1 = -7;
for (k3 = 0; k3 <= 623; k3++) // Sort every 5 cards in a hand
{
n1 = n1 + 7;
x1 = x3.substr(n1,7); x2 = x1.substr(5,2);
for (k2 = 0; k2 <= 4; k2++)
{
x4 = x1.substr(k2,1);
for (k1 = 0; k1 <= 51; k1++)
{
if (x4 == mNum[k1])
{
aSort[k1] = x4; // Within-typed sorting
goto aSkip;
}
}
aSkip: k1 = 0;
}
for (k2 = 51; k2 >= 0; k2--) //change ascending order to decending one
{
x2 = aSort[k2] + x2;
aSort[k2] = "";
}
aHand = x2 + "0000"; //Padding 4 zeros to be standardized 11 in length
appFile << aHand << endl;
}
appFile.close();
}
void Point8() //straight and flush: 40. No sorting is needed.
{ // Each hand is already in ascending order
int k1,k2, n1, n2;
int aCard[] = {0,1,2,3,4,0,9,10,11,12},bCard[50]; // Whole column's rating
string x1, aHand, bHand,Rating[] = {"4","=","5","6","7","8","9",":",";","<"};
//Ace is counted as face value 0 in hand (0,1,2,3,4) but is valued 13 in hand
//(0,9,10,11,12); Only one card's face value is needed for within-type hands
//comparison (e.g. Hand A > B)
for (k1 = 0; k1 <= 9; k1++) // First 2 hands
bCard[k1] = aCard[k1];
n1 = 9;
for (k2 = 1; k2 <= 8; k2++) // Complete the first column's 10 hands;
{
for (k1 = k2; k1 <= k2 + 4; k1++)
{
n1++;
bCard[n1] = k1;
}
}
for (k2 = 0; k2 <= 39; k2+= 13) // from column 1, permutate to all 4 columns
{
for (k1 = 0; k1 <= 49; k1++)
{
n1 = k2 + bCard[k1];
aHand = aHand + mNum[n1];
}
} // string aHand contains all 40 hands (200 characters)
ofstream appFile("2598960.txt", ios::app);
n1 = -5; n2 = -1;
for (k1 = 0; k1 <= 39; k1++)
{ // One character is enough to do within type
n1 = n1 + 5; n2 = k1 % 10; // comparison. pad "0000" to make length 6
bHand = aHand.substr(n1,5) + "l" + Rating[n2] + "0000";
appFile << bHand << endl; // "l": letter l
} // 01234l40000 is the smallest; 09:;< is the biggest
appFile.close(); // string 0-4: 5 card's IDs; 5: Type l
} // 6: the card with the biggest value
// 7-10: 4 zeros for padding purpose
void Replace9()// This function sorts hands (point 0 - point 3); Instead of
{ // pre-Played ascending order of the 5 cards, the new order: pair and triple,
int k1,k2,k3,n1,n2,aEnd; //Ace and then descending order of face value.
string x1,x2,aCard,aAce = "0=JW",aHand, bHand,aSort[52], aZero = "00000";
// Point 0, 1 2 3
aEnd = 1302540 + 1098240 + 123552 + 54912; // Replace n cards means keeping 5-n cards
ifstream InFile("2598960.txt",ios::in); // and adding n cards. Now a hand is: e.g.
ofstream OutFile("2598960a.txt", ios::out); //0123Bd=53210B321
for (k3 = 1; k3 <= aEnd; k3++) //0123B Heart: Ace,2,3, 4 + Diamond: 6
{ //d=5321: High card, face: 13,5,3,2,1
InFile >> aHand; //0B321: Keeping 2 cards (0B) and adding 3.
aCard = "",bHand = "";
for (k2 = 0; k2 <= 4; k2++)
{
x1 = aHand.substr(k2,1);
for (k1 = 0; k1 <= 51; k1++)
{
if (x1 == mNum[k1]) break;
}
n1 = k1 % 13; aSort[n1] = aSort[n1] + x1;
}
for (k2 = 12; k2 >= 0; k2--)
{
x1 = aSort[k2]; n1 = x1.length();
if (n1 == 1)
{
aCard = aCard + x1; //Non pair and not triple cards
}
else if (n1 > 1) // Pick up pairs and triple
bHand = bHand + x1;
aSort[k2] = "";
}
x1 = aCard; n1 = x1.length();
if (n1 > 1) x2 = x1.substr(n1-1,1);
if (aAce.find(x2,0) != -1)
aCard = x2 + x1.substr(0,n1-1);
bHand = aHand + bHand + aCard;
OutFile << bHand << endl; // Each hand is 16 in length
}
aEnd = aEnd + 1;
for (k3 = aEnd; k3 <= 2598960;k3++) // For point 4 or higher, no card replacement
{
InFile >> x1;
x1 = x1 + aZero; //Padding "00000" to the end.
OutFile << x1 << endl;
}
OutFile.close();
InFile.close();
}
void Sort10() //In this compiler, only 250,000 array length is allowed.
{ //So, this function uses 2-step sorting for 2,598,960 hands
//Set up 19,600 headings. Each hand adds to the heading array,which
int k1,k2,k3,n1 = -1,n2; // has the same 3 cards with the heading array.
string x1,x2,x3,aHead[19600],aGroup[19600];
for (k3 = 0; k3 <= 47; k3++)
{
x3 = mNum[k3];
for (k2 = k3 + 1; k2 <= 48; k2++)
{
x2 = x3 + mNum[k2];
for (k1 = k2 + 1; k1 <= 49;k1++)
{
n1++;
aHead[n1] = x2 + mNum[k1];
}
}
}
n1 = -1;
ifstream InFile("2598960a.txt");
for (k2 = 0; k2 < 2598960; k2++)
{
InFile >> x1; x2 = x1.substr(0,3); //e.g. hand 01234,012Wb and 012bc go to
for (k1 = 0; k1 < 19600;k1++) // the same group and become one single string
{
if (x2 == aHead[k1])
{
aGroup[k1] = aGroup[k1] + x1;
goto aSkip;
}
}
aSkip: k1 = 0;
}
InFile.close();
ofstream OutFile("2598960b.txt",ios::out); //Sorting step 2:
for (k2 = 0; k2 < 19600; k2++)
{
x1 = aGroup[k2];
n1 = (x1.length() / 16) - 1;
if (n1 == 0)
OutFile << x1 << endl; // Some headings have only one hand. No sorting
else
{
n2 = -16;
for (k1 = 0; k1 <= n1; k1++) // Dissemble each string int hands 1175
{
n2 = n2 + 16;
mMove[k1] = x1.substr(n2,16); //Store hands into global array mMove[n]
}
QuickSort(0,n1); // Within group sorting
for (k1 = 0; k1 <= n1; k1++)
OutFile << mMove[k1] << endl;// Sorting 2,598,960 hands completed.
}
}
OutFile.close();
}
void LineUp11() //Structure 2,598,960 hands into 2548 lines and 1020 hands per line
{
int k1,k2,n1,n2, n3,aEnd,bEnd;
string x1,x2;
n1 = 2598960;
for (k1 = 3000; k1 >= 2000; k1--) // This loop chooses the 2548 by 1020 structure
{
n2 = n1 / k1;
n3 = n1 % k1;
if (n3 == 0 && n2 > 1000)
{
aEnd = k1; bEnd = n2;
goto aSkip;
}
}
aSkip: k1 = 0;
ifstream InFile("2598960b.txt",ios::in); // Group 2,598,960 hands into 2548 lines
ofstream OutFile("2548c.txt",ios::out); // separating 2 hands with a space.
for (k2 = 1; k2 <= aEnd; k2++)
{
x2 = "";
for (k1 = 1; k1 <= bEnd; k1++)
{
InFile >> x1; x2 = x2 + x1 + " ";
}
OutFile << x2 << endl;
}
OutFile.close();
InFile.close();
}
void QuickSort(int aLow,int aHigh)
{
int bLow, bMiddle, bHigh;
string bKey, bTemp;
bLow = aLow; bHigh = aHigh;
bMiddle = (bLow + bHigh) / 2;
bKey = mMove[bMiddle];
while (bLow <= bHigh)
{
while (mMove[bLow] < bKey) bLow = bLow + 1;
while (mMove[bHigh] > bKey) bHigh = bHigh - 1;
if (bLow <= bHigh)
{
bTemp = mMove[bLow];
mMove[bLow] = mMove[bHigh]; mMove[bHigh] = bTemp;
bLow = bLow + 1; bHigh = bHigh - 1;
}
}
if (aLow < bHigh) QuickSort(aLow,bHigh);
if (bLow < aHigh) QuickSort(bLow,aHigh);
}
Sub-program 2 (Poker Series)
Playing one million games and save the games in a text form (one game per line)
Summing up the dealer's total score in one million games (4 million bets)
void aMain();
void SetUp();
void Hands1();
string Poker2(string);
string Retrieve3(string);
string mNum[52],nNum;
string mHand[2549], mHead[2549], mCard;
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
int k1;
string x1,x2;
srand(time(0));
SetUp();
Hands1();
ifstream InFile("1mGame1.txt",ios::in);
ofstream OutFile("1mGame2.txt",ios::out);
for (k1 = 1; k1 <= 1000000; k1++) //This loop runs about 38 seconds
{
InFile >> x1;
x2 = Poker2(x1);
OutFile << x2 << endl;
}
OutFile.close();
InFile.close();
}
void SetUp()
{
int k1;
string x1;
for (k1 = 0; k1 <= 51; k1++) //Consecutive 52 ASCII characters for 52 cards
{
mNum[k1] = char(k1+ 48);
nNum = nNum + mNum[k1]; //One string representing 52 cards.
}
ifstream InFile("2548c.txt",ios::in); //Load up 2 millon plus hand entities
mHead[2548] = "xxxxx"; //Ending line
for (k1 = 0; k1 <= 2547; k1++)
{
getline(InFile,x1);
mHand[k1] = x1; mHead[k1] = x1.substr(0,5);
} // A hand entity starts with a 5-card hand
InFile.close();
}
void Hands1()//Line up one million poker games (One dealer vs 4 players)
{ // Get ready to play games.
int k1,k2,k3,n1, n2, bCard[25];
string x1, x2,aCard, aSort[52], aHand;
char c1[25];
ofstream OutFile("1mGame1.txt",ios::out); // Card-shuffling: x1 = "america";
for (k3 = 1; k3 <= 1000000; k3++) // 0123456
{ // for k2 = 7 to 1 k2--
x1 = nNum; aCard = ""; // n1 = rand() % k2 (7)
for (k2 = 52; k2 >= 1; k2--) // n1 = 5; aCard = aCard + "c"
{ // Delete "c"; x1 = "ameria";
n1 = rand() % k2; // 012345
aCard = aCard + x1.substr(n1,1);//for k2 = 6 to 1 k2--
x1.erase(n1,1); // n1 = rand() % k2 (6)
} // n1 = 1; aCard = aCard + "m"
// Delete "m"; x1 = "aeria";
// 01234
aCard.copy(c1,25); //aCard (25 cards) distrubute to 5 players.
for (k2 = 0; k2 <= 24; k2++)
bCard[k2] = int(c1[k2]) - 48; //representation from string to integer
n1 = -1; x2 = "";
for (k2 = 0; k2 <= 4; k2++)
{
x1 = "";
for (k1 = 0; k1 <= 4; k1++)
{
n1++;
n2 = bCard[n1]; aSort[n2] = mNum[n2];
}
for (k1 = 0; k1 <= 51; k1++)
{
x1 = x1 + aSort[k1];
aSort[k1] = "";
}
x2 = x2 + Retrieve3(x1);//Get 5 hand entities (each is 16 characters in length)
}
aHand = x2 + aCard.substr(25,27); //80 characters + 27 extra cards for replacement
OutFile << aHand << endl;
}
OutFile.close();
}
//This function plays a poker game (deciding dealer wins, loses or ties
// Replacing 0-3 cards: 1. Pick up the rating letter(d) from the length 16 line (position 5)
// Locate the letter's position(n1 = 0) in aType and through cross-reference n1 = aLen[n1]
// n1 = 2; n2 = 5 - n1; Retain 2 cards from the hand and add 3 (n2) cards from Repla
string Poker2(string pHand) // Each line: first 16 characters belong to the dealer
{ // The rest are for the other 4 players
int aLen[] = {2,2,4,3,5,5,5,5,5},k1,n1,n2, bLen, aStart = 0;
string aType = "defghijkl", x1, x2, x3; // Dealer's score range: -4 to 4 (4 bets)
string aNum[] = {"-4","-3","-2","-1"," 0"," 1"," 2"," 3"," 4"}; // For line up string.
string aGame[5],aHand,bHand[5],aRate1,aRate2,bRate[5],aHead, Repla,aWin[5];
n1 = -16;
for (k1 = 0; k1 <= 4; k1++)
{
n1 = n1 + 16; // d:point 0
aGame[k1] = pHand.substr(n1,16); //e.g. 0123Bd=53210B321: 0123B d=5321 0B321
} // 5 cards face keep
Repla = pHand.substr(80,27); //pick 0-3 cards from Repla //value 0B3
for (k1 = 0; k1 <= 4; k1++)
{
x1 = aGame[k1];
aHand = x1.substr(0,5); // Ascending order of 5 cards
aRate1 = x1.substr(5,1); aRate2 = x1.substr(5,6); //Letter from defghijkl
if (aRate1 < "h") // No replacement for rating > 3-kind
{
aHead = x1.substr(11,5); //Reversed order of aHand
n1 = aType.find(aRate1,0); n1 = aLen[n1];
n2 = 5 - n1;
x2 = aHead.substr(0,n1) + Repla.substr(aStart,n2); //Retain n1 cards and add
aStart = aStart + n2; //n2 cards
x3 = Retrieve3(x2); // from 5-cards, Retrieves a hand entity of length 16
aHand = x1.substr(0,5); aRate2 = x1.substr(5,6);
}
bHand[k1] = aHand; bRate[k1] = aRate2; //Replace the original hand.
}
x1 = bHand[0]; x2 = bRate[0]; //Compare dealer's rating against the other four
n1 = 4; // n1 sum up the dealer's score
for (k1 = 1; k1 <= 4; k1++)
{
if (x2 < bRate[k1]) //Dealer loses
{
n1--; aWin[k1] = " 1";
}
else if (x2 > bRate[k1]) //Dealer wins
{
n1++; aWin[k1] = "-1";
}
else
{
n1 = n1 + 0; aWin[k1] = " 0"; //Dealer ties
}
}
aWin[0] = aNum[n1]; x1 = "";
for (k1 = 0; k1 <= 4; k1++)
x1 = x1 + bHand[k1] + " " + bRate[k1] + aWin[k1] + " ";
return x1; //Assemble back to 16-length entity.
} //Each line 107 characters.
string Retrieve3(string pHand) // Input a hand (5 cards) and get its rating and
{ // its reordered 5 cards for replacement purpose.
int k1,k2,n1;
string x1,aLine,aHand, aSort[52];
aHand = pHand;
for (k2 = 0; k2 <= 4; k2++) //Sorting hand ascendingly
{
x1 = aHand.substr(k2,1);
for (k1 = 0; k1 <= 51; k1++)
{
if (x1 == mNum[k1])
aSort[k1] = x1;
}
}
aHand = "";
for (k1 = 0; k1 <= 51; k1++)
aHand = aHand + aSort[k1];
for (k1 = 0; k1 <= 2548; k1++)//2-step search (similar to looking up words in a dictionary
if (aHand < mHead[k1]) //There are 2 million plus Hands. But this compiler only
goto aSkip; //allows < 250,000 array size.
aSkip:
aLine = mHand[k1-1]; //1. Decide what line the hand is in. 2. Search the line
n1 = aLine.find(aHand,0);
aHand = aLine.substr(n1,16);
return aHand;
}
Sub-program 3 (Poker Series)
Play a single game and display card-replacement's effect on a hand's strength.
void aMain();
void SetUp();
void Poker();
string Hands();
string Retrieve(string);
void SumUp();
string mNum[52],nNum,mName[52];
string mHand[2549], mHead[2549];
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
int k1;
string x1;
srand(time(0));
SetUp();
Poker();
SumUp();
}
void SetUp()
{
int k1;
string x1;
for (k1 = 0; k1 <= 51; k1++)
{
mNum[k1] = char(k1+ 48);
nNum = nNum + mNum[k1] ;
}
ifstream InFile("2548c.txt",ios::in);
mHead[2548] = "xxxxx";
for (k1 = 0; k1 <= 2547; k1++)
{
getline(InFile,x1);
mHand[k1] = x1; mHead[k1] = x1.substr(0,5);
}
InFile.close();
ifstream aInFile("cName.txt",ios::in);
for (k1 = 0; k1 <= 51; k1++)
aInFile >> mName[k1];
}
void Poker() // Play one poker game.
{
int aLen[] = {2,2,4,3,5,5,5,5,5},k1,k2,n1,n2, bLen, aStart = 0,aWin[5];
string aGame[5],aHand,bHand[5],aRate1,aRate2,bRate[5],aHead, Repla;
string Hand1[5],Rate1[5],Hand2[5],Rate2[5], Name1[5], Name2[5];
string aType = "defghijkl", x1, x2, x3;
char c1[5];
aHand = Hands();
n1 = -16;
for (k1 = 0; k1 <= 4; k1++)
{
n1 = n1 + 16;
aGame[k1] = aHand.substr(n1,16);
}
Repla = aHand.substr(80,27);
for (k1 = 0; k1 <= 4; k1++)
{
x1 = aGame[k1];
aHand = x1.substr(0,5);
aRate1 = x1.substr(5,1); aRate2 = x1.substr(5,6);
Hand1[k1] = aHand; Rate1[k1] = aRate2;
if (aRate1 < "h")
{
aHead = x1.substr(11,6);
n1 = aType.find(aRate1,0); n1 = aLen[n1];
n2 = 5 - n1;
x2 = aHead.substr(0,n1) + Repla.substr(aStart,n2);
aStart = aStart + n2;
x3 = Retrieve(x2);
aHand = x3.substr(0,5); aRate2 = x3.substr(5,6);
}
Hand2[k1] = aHand; Rate2[k1] = aRate2;
}
x1 = Rate2[0];
n1 = 0;
for (k1 = 1; k1 <= 4; k1++)
{
if (x1 < Rate2[k1])
{
n1--; aWin[k1] = 1;
}
else if (x1 > Rate2[k1])
{
n1++; aWin[k1] = -1;
}
else
{
n1 = n1 + 0; aWin[k1] = 0;
}
}
aWin[0] = n1;
for (k2 = 0; k2 <= 4; k2++)
{
Hand1[k2].copy(c1,5);
x1 = "";
for (k1 = 0; k1 <= 4; k1++)
{
n1 = int(c1[k1]) - 48;
x1 = x1 + mName[n1] + ".";
}
Name1[k2] = x1;
}
for (k2 = 0; k2 <= 4; k2++)
{
Hand2[k2].copy(c1,5);
x1 = "";
for (k1 = 0; k1 <= 4; k1++)
{
n1 = int(c1[k1]) - 48;
x1 = x1 + mName[n1] + ".";
}
Name2[k2] = x1;
}
cout << "Poker Game (1 dealer vs 4 Players)" << endl;
cout << "Before card swaping" << endl;
for (k1 = 0; k1 <= 4; k1++)
{
cout << Hand1[k1] << " " << Rate1[k1] <<" " + Name1[k1] << endl;
}
cout << endl;
cout << "After card swaping" << endl;
cout << "Hand Rate Card Name Scores" << endl;
for (k1 = 0; k1 <= 4; k1++)
cout << Hand2[k1] + " " + Rate2[k1] + Name2[k1] << " " << aWin[k1] << endl;
cout << endl;
cout << "T = 10; A = Ace; J = Jack; Q = Queen; K = King " << endl;
cout << "H = Heart; D = Diamond; C = Club; S = Spade" << endl;
cout << "Line 1: Dealer; 2-5: guest players" << endl << endl;
}
string Hands()
{
int k1,k2,k3,n1, n2, bCard[25];
string x1, x2,aCard, aSort[52], aHand;
char c1[25];
x1 = nNum;
for (k1 = 52; k1 >= 1; k1--)
{
n1 = rand() % k1;
aCard = aCard + x1.substr(n1,1);
x1.erase(n1,1);
}
aCard.copy(c1,25);
for (k1 = 0; k1 <= 24; k1++)
bCard[k1] = int(c1[k1]) - 48;
n1 = -1;
for (k2 = 0; k2 <= 4; k2++)
{
x1 = "";
for (k1 = 0; k1 <= 4; k1++)
{
n1++;
n2 = bCard[n1]; aSort[n2] = mNum[n2];
}
for (k1 = 0; k1 <= 51; k1++)
{
x1 = x1 + aSort[k1];
aSort[k1] = "";
}
x2 = x2 + Retrieve(x1);
}
aHand = x2 + aCard.substr(25,27);
return aHand;
}
string Retrieve(string pHand)
{
int k1,k2,n1;
string x1,x2,aLine,aHand, aSort[52];
aHand = pHand; //The 5 cards of a hand must be in ascending order
for (k2 = 0; k2 <= 4; k2++)
{
x1 = aHand.substr(k2,1);
for (k1 = 0; k1 <= 51; k1++)
{
if (x1 == mNum[k1])
aSort[k1] = x1;
}
}
aHand = "";
for (k1 = 0; k1 <= 51; k1++)
aHand = aHand + aSort[k1];
for (k1 = 0; k1 <= 2548; k1++)
{
if (aHand < mHead[k1])
goto aSkip;
}
aSkip:
aLine = mHand[k1-1];
n1 = aLine.find(aHand,0);
aHand = aLine.substr(n1,16);
return aHand;
}
void SumUp()
{
int k1,k2, n1,n2, n3 = 0, aSum = 0,aCount[3] = {0},aIndex[] = {0,0,0,0,1,2,2,2,2};
string x1,x2,aName[] = {"Loss","Tie","Win"};
ifstream InFile("1mGame2.txt",ios::in);
for (k1 = 1; k1 <= 1000000; k1++)
{
getline(InFile,x1); x2 = x1.substr(12,2);
n1 = atoi(x2.c_str()); n2 = n1 + 4; n2 = aIndex[n2];
aSum = aSum + n1; aCount[n2] = aCount[n2] + 1;
//cout << k1 << " " << n2 << endl;
}
InFile.close();
for (k1 = 0; k1 <= 2; k1++)
{
n3 = n3 + aCount[k1];
cout << aName[k1] << ": " << aCount[k1] << endl;
}
cout << "Game count: " << n3 << endl;
}
***** 4
Breaking Enigma Codes Program
Data Representation (For the purpose of developing into an algorithem)
Consecutive 95 ASCII numbers (all Windows keyboard displayable characters.
Its integer equivalence numbered 32 to 126: from space,! to } and ~
I re-index them into 0 - 95 and 96 - 189 (make them into a merry-go-around.
list. Index - 32 = Re-index)
0 sp 10 * 20 4 30 > 40 H 50 R 60 \ 70 f 80 p 90 z
1 ! 11 + 21 5 31 ? 41 I 51 S 61 ] 71 g 81 q 91 {
2 " 12 , 22 6 32 @ 42 J 52 T 62 ^ 72 h 82 r 92 |
3 # 13 - 23 7 33 A 43 K 53 U 63 _ 73 i 83 s 93 }
4 $ 14 . 24 8 34 B 44 L 54 V 64 ` 74 j 84 t 94 ~
5 % 15 / 25 9 35 C 45 M 55 W 65 a 75 k 85 u 95 sp **
6 & 16 0 26 : 36 D 46 N 56 X 66 b 76 l 86 v 96 !
7 ' 17 1 27 ; 37 E 47 O 57 Y 67 c 77 m 87 w 97 "
8 ( 18 2 28 < 38 F 48 P 58 Z 68 d 78 n 88 x 98 #
9 ) 19 3 29 = 39 G 49 Q 59 [ 69 e 79 o 89 y 99 $
100 % 110 / 120 9 130 C 140 M 150 W 160 a 170 k 180 u
101 & 111 0 121 : 131 D 141 N 151 X 161 b 171 l 181 v
102 ' 112 1 122 ; 132 E 142 O 152 Y 162 c 172 m 182 w
103 ( 113 2 123 < 133 F 143 P 153 Z 163 d 173 n 183 x
104 ) 114 3 124 = 134 G 144 Q 154 [ 164 e 174 o 184 y
105 * 115 4 125 > 135 H 145 R 155 \ 165 f 175 p 185 z
106 + 116 5 126 ? 136 I 146 S 156 ] 166 g 176 q 186 {
107 ' 117 6 127 @ 137 J 147 T 157 ^ 167 h 177 r 187 |
108 - 118 7 128 A 138 K 148 U 158 _ 168 i 178 s 188 }
109 , 119 8 129 B 139 L 149 V 159 ` 169 j 179 t 189 ~
(go around from 95 **)
How does Enigma code and decode text?
Enigma coding is called sectional and rotational substitution.
Suppose
1. the key for coding and decoding is: america
2. the length is 4: amer. We get ASCCI numbers from amer: 66,78,70,83
3. the text: To err is human and to forgive divine.
Sectionalize the messege (section of 4):
To e
rr i
s hu
man
and
to f
orgi
ve d
ivin
eTo
Flip columns to rows and code
Trsmatovie + 66
or anorevt + 78
hnd g io + 70
eiu fidn + 83
Decode:
coded text + 95 - (66,78,70,83)
Flip rows back to columns
Break coded text
1. Try and error (length 2 - 6)
2. Character-frequency count (row by row): space, e and t (from high to low)
3. In the coded text of Declaration of Independence, Row 1. the highest
frequency count is "u". This means u equal to space. u minus space = 53.
4. Swap all characters in Row 1 from string to integer and (+ 95 - 53) % 95.
Swap all integers back to string. You get the original text.
Program:
void aMain();
void SetUp1();
void Code2();
void Decode3();
void BreakCode4();
int GetKey5(string);
string mNum[190],mAbort, mCut = " "; // No double space is allowed
string mKey = "To err is human and to forgive divine"; //used to code and decode text
int nKey[25];
string mName[] = {"","Text1.txt", "Text2.txt","Text3.txt"};
int nName = 3;
// Text1-3: DECLARATION OF INDEPENDENCE, Donald Trump's Speech, Joe Biden's Speech
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
SetUp1();
Code2();
Decode3();
BreakCode4();
}
void SetUp1()
{
int k1, n1 = -1;
string x1,x2, x3, aNum,bNum;
char c1[25];
for (k1 = 0; k1 <= 94; k1++)
{
x1 = char(k1+32);// The 95 (32-126) characters are now re-indexed
mNum[k1] = x1; // to 0-94. nNum[n] - 32 = mNum[n]
mNum[k1 + 95] = x1;
if (k1 == 62 or k1 == 91 or k1 == 93 or k1 == 94)
mAbort = mAbort + x1; // mAbort = "^{}~".When one or two of
} //the mAbort are found,decoding has failed.
mKey.copy(c1,24); // Change the key from string to integer
for (k1 = 0; k1 <= 23; k1++)
nKey[k1] = int(c1[k1]) - 31; // Add numbers (1-94)
ifstream InFile(mName[nName].c_str(), ios::in); //Store whole text in a single string
do
{
getline(InFile,x1);
x2 = x2 + x1 + " ";
} while (!InFile.eof());
InFile.close();
do
{
n1 = 0;
n1 = x2.find(mCut,n1); //Keep only those characters which show up in PC keyboard
if (n1 != -1) // No double spaces
x2.erase(n1,1); // change all possible double spaces to single space.
} while (n1 != -1);
aNum = mNum[0]; bNum = mNum[94];
n1 = x2.length();
for (k1 = 0; k1 < n1; k1++)
{
x1 = x2.substr(k1,1);
if (x1 >= aNum && x1 <= bNum)//Keep only those characters
x3 = x3 + x1; // that are on a PC keyboard.
}
ofstream OutFile("TextA.txt", ios::out);
OutFile << x3 << endl;
OutFile.close();
//TextA: cleaned original text, B: coded text, C: decoded text.X: broken text
}
void Code2()
{
int k1, n1 = -1, n2, aLen;
string x1;
char c1[39999];
ifstream InFile("TextA.txt", ios::in);
getline(InFile,x1);
InFile.close();
aLen = x1.length();
x1.copy(c1,aLen); x1 = ""; // Change string to char
for (k1 = 0; k1 < aLen; k1++)
{
n1 = (n1 + 1) % 24;
n2 = int(c1[k1]) - 32 + nKey[n1];//char to integer.Code the text
x1 = x1 + mNum[n2];
}
do
{
n1 = 0;
n1 = x1.find(mCut,n1); // Single spacing only
if (n1 != -1)
x1.erase(n1,1);
} while (n1 != -1);
ofstream OutFile("TextB.txt", ios::out); // TextB: coded text
OutFile << x1 << endl;
OutFile.close();
}
void Decode3()
{
int k1, n1 = -1, n2, aLen;
string x1;
char c1[39999];
ifstream InFile("TextB.txt", ios::in);
getline(InFile,x1);
InFile.close();
aLen = x1.length();
x1.copy(c1,aLen); x1 = "";
for (k1 = 0; k1 < aLen; k1++)
{
n1 = (n1 + 1) % 24;
n2 = int(c1[k1]) - 32 + 95 - nKey[n1];
x1 = x1 + mNum[n2];
}
do
{
n1 = 0;
n1 = x1.find(mCut,n1);
if (n1 != -1)
x1.erase(n1,1);
} while (n1 != -1);
ofstream OutFile("TextC.txt", ios::out);//Decoded text
OutFile << x1 << endl;
OutFile.close();
}
void BreakCode4()
{
int k1, k2, k3,n1, n2, n3,aLen, bLen,aStep,aKey[25], bKey;
string x1,x2, aText,bText[25], cText[25];
bool aSave = false;
char c1[3333];
ifstream InFile("TextB.txt", ios::in);
getline(InFile,aText);
InFile.close();
aLen = aText.length();
for (k3 = 15; k3 <= 25; k3++) // Try text length 15 - 25
{ // Text: 123456780
aStep = k3; // Section: 3
n1 = aStep - (aLen % aStep); // New text: 123\456/789/012
x1 = aText + aText.substr(0,n1);//Section: 4
bLen = (aLen + n1) / aStep; //New text: 1234\5678/9012
for (k2 = 0; k2 < aStep; k2++) //After breaking: text = newtext(0,10)
{
n1 = k2; x2 = "";
for (k1 = 0; k1 < bLen; k1++)
{
x2 = x2 + x1.substr(n1,1);
n1 = n1 + aStep;
}
bText[k2] = x2;
}
for (k2 = 0; k2 < aStep; k2++)
{
x1 = bText[k2]; x1.copy(c1,bLen);
bKey = GetKey5(x1); x2 = ""; //Get a key from a section of text
n3 = 0;
for (k1 = 0; k1 < bLen; k1++)
{
n1 = int(c1[k1]) - 32 + 95 - bKey; //Deduct the key
x2 = x2 + mNum[n1];
n2 = mAbort.find(mNum[n1],0);
if (n2 != -1) n3++;
if (n3 > 2) goto aSkip; // If the new text has 3 or more
} // unusual character, abort.
cText[k2] = x2;
}
x1 = "";
for (k2 = 0; k2 < bLen; k2++)
{
for (k1 = 0; k1 < aStep; k1++)
x1 = x1 + cText[k1].substr(k2,1);
}
x1 = x1.substr(0,aLen); //Cut off the tail
aSave = true;
break;
aSkip: k1 = 0;
}
if (aSave == true)
{
n1 = 0;
do
{
n1 = x1.find(mCut,n1);
if (n1 != -1)
x1.erase(n1,1); //Remove any possible double space.
} while (n1 != -1);
ofstream OutFile("TextX.txt",ios::out); //Return coded text to original
OutFile << x1 << endl;
OutFile.close();
}
}
int GetKey5(string pText) // Through frequence count, retrieve the keys
{ // row by row
int k1,n1,aLen, aSum[95] = {0},bSum[95],aText[999], aKey;
char c1[999];
aLen = pText.length();
pText.copy(c1,aLen);
for (k1 = 0; k1 <= aLen; k1++)
{
n1 = int(c1[k1]) - 32; // from 32-126 to 0-95
aText[k1] = n1;
aSum[n1] = aSum[n1] + 1; // Sum the appearing of each characters
}
for (k1 = 0; k1 <= 94; k1++)
{
n1 = aSum[k1];
bSum[k1] = k1;
}
n1 = 0;
for (k1 = 0; k1 <= 94; k1++)
{
if (n1 < aSum[k1])
{
n1 = aSum[k1];
aKey = k1; //Get the number with the highest frequency
} // consider it the key: the space(32)
}
return aKey; // Input a text and output a number
}
***** 5
Programming Knight's Tours Part 1 (total: 3 parts)
Tasks:
1. Walk a knight's closed tour (64 moves)
2. Display a formatted knight's tour
3. Print, in a text file, all 64 knight's tours
starting from square 1 or 2 or 3...;
Data Representation
1. 3 ways to represent the chessboard
1-D 2-D ASCII (consecutive value)
0 1 2 3 4 5 6 7 21 22 23 24 25 26 27 28 0 1 2 3 4 5 6 7
8 9 10 11 12 13 14 15 31 32 33 34 35 36 37 38 8 9 : ; < = > ?
16 17 18 19 20 21 22 23 41 42 43 44 45 46 47 48 @ A B C D E F G
24 25 26 27 28 29 30 31 51 52 53 54 55 56 57 58 H I J K L M N O
32 33 34 35 36 37 38 39 61 62 63 64 65 66 67 68 P Q R S T U V W
40 41 42 43 44 45 46 47 71 72 73 74 75 76 77 78 X Y Z [ \ ] ^ _
48 49 50 51 52 53 54 55 81 82 83 84 85 86 87 88 ` a b c d e f g
56 57 58 59 60 61 62 63 91 92 93 94 95 96 97 98 h i j k l m n o
2. Representing a tour (Starting at square 0 and ending at 17)
0:4>O^oe_ndj`Q@1;5?ND39HYhblfU[JPakZiXI8BS]gmcTE6GVL=7FWM<2CR\KA
3. How to move the knight within the bounds and in L shape?
Suppose the following is a chessboard
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29 0 1 2 3 4 5 6 7
30 31 32 33 34 35 36 37 38 39 8 9 10 11 12 13 14 15
40 41 42 43 44 45 46 47 48 49 16 17 18 19 20 21 22 23
50 51 52 53 54 55 56 57 58 59 24 25 26 27 28 29 30 31
60 61 62 63 64 65 66 67 68 69 32 33 34 35 36 37 38 39
70 71 72 73 74 75 76 77 78 79 40 41 42 43 44 45 46 47
80 81 82 83 84 85 86 87 88 89 48 49 50 51 52 53 54 55
90 91 92 93 94 95 96 97 98 99 56 57 58 59 60 61 62 63
00 01 02 03 04 05 06 07 08 09 (100-109)
10 11 12 13 14 15 16 17 18 19 (110-119)
Suppose the knight is on square 54.
The 8 squares he can move to: 33,35,42,46,62,66,73,75
How to get those 8 moves?
Square 54 + (-21,-19,-12,-8,8,12,19,21) = 33,35,42,46,62,66,73,75
Suppose the knight is on square 21.
Square 21 + (-21,-19,-12,-8,8,12,19,21) = 0,2,9,13,29,33,40,42
Next we set up a filter(bFilter[120]): bFilter[0-20,100-119] and bFilter[20-90,29-99] = -1
We pass 0,2,9,13,29,33,40,42 through f2[n], we get -1,-1,-1,-1,10,17
Keeping non -1, we get 10,17. So square 0 can only move to 10 and 17.
we then organize all the moves into mStart[64] and mEnd[64], mIndex[n] .
aStart = mStart[0]; aEnd = mEnd[0];
for (k1 = aStart; k1 <= aEnd; k1++)
cout << mIndex[k1] << endl; 10,17
//Program 1: One single knight's closed tour
int mIndex[336], mStart[64], mEnd[64];
// The mRate is copied from "Visual Basic 6: How to Program"
// mRate is the accesibility numbers. e.g. Square 0 can go to square 10 and 17 (rate = 2)
int mRate[] = {2,3,4,4,4,4,3,2,3,4,6,6,6,6,4,3,4,6,8,8,8,8,6,4,4,6,8,8,8,8,6,
4,4,6,8,8,8,8,6,4,4,6,8,8,8,8,6,4,3,4,6,6,6,6,4,3,2,3,4,4,4,4,3,2};
string mNum[64], mTour, mCheck[64]; //nNum is formatted numbers
string nNum[] = {" 0"," 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9","10","11","12","13",
"14","15","16","17","18","19","20","21","22","23","24","25","26","27","28",
"29","30","31","32","33","34","35","36","37","38","39","40","41","42","43",
"44","45","46","47","48","49","50","51","52","53","54","55","56","57","58",
"59","60","61","62","63","64"};
void aMain();
void SetUp1();
void Tour2();
void Save3();
void Show4();
int main(int argc, char** argv)
{
int k1,k2,n1,n2;
string x1,x2;
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
SetUp1();
Tour2();
Save3();
Show4();
}
void SetUp1()
{
int k1, k2, n1, n2, aCount = -1, f1[64], f2[120];
int aStep[] = {12,-21,-19,21,-12,-8,19,8};
string x1, x2;
char c1[64];
for (k1 = 0; k1 <= 63; k1++)
mNum[k1] = char(k1+48);//Set up integer numbers for string ASCII conversion.
for (k1 = 0; k1 <= 119; k1++)
f2[k1] = -1;
for (k2 = 21; k2 <= 91; k2+= 10)
{
for (k1 = k2; k1<= k2 + 7; k1++)
{
aCount++;
f1[aCount] = k1; f2[k1] = aCount;
} //f1[0] = 21; f2[21] = 0;
}
aCount = -1; // Use knight's positions as keys
for (k2 = 0; k2<= 63; k2++) // to retrieve its valid moves
{
n1 = f1[k2]; x1 = "";
mStart[k2] = aCount + 1;
for (k1 = 0; k1<= 7; k1++)
{
n2 = n1 + aStep[k1];
n2 = f2[n2];
if (n2 != -1)
{
aCount++;
mIndex[aCount] = n2; // mIndex = knight's move indexes
x1 = x1 + mNum[n2];
}
}
mEnd[k2] = aCount; mCheck[k2] = x1; // Each square's valid move sum
} // e.g Square 0's valid moves: :A (10, 17)
}
void Tour2()
{
int k1, k2, n1, aMove = 0, aStart, aEnd, aMin;
string x1,x2,x3;
char c1[65];
mTour = mNum[aMove]; // Starting at square 0 and ending at square 17
for (k2 = 1; k2 <= 63; k2++) // which is a move away from square 0
{
mRate[aMove] = 19; // Use 19 to lock up the square
aStart = mStart[aMove]; aEnd = mEnd[aMove]; // Square numbers as keys to retrieve
aMin = 19; // valid moves
for (k1 = aStart; k1 <= aEnd; k1++) // When a square is stepped on its rating is
{ // assigned 99 and all squares, which have
n1 = mIndex[k1]; mRate[n1] = mRate[n1] - 1; // access to that 99 valued ,
if (aMin > mRate[n1]) // is cut by 1 in their rating.
{
aMin = mRate[n1]; aMove = n1;//Choose the lowest rating number
} // for next move.
}
mTour = mTour + mNum[aMove];//64 position numbers = 64 moves
}
x1 = mTour + "0";//Check if all 64 moves are valid (in L shape)
x2 = x1.substr(0,62) + "KA0"; // Insert an error
// Error Test for all 64 moves' validity
x2.copy(c1,65);
for (k1 = 0; k1 <= 63; k1++)
{
x1 = x2.substr(k1,1);
n1 = c1[k1+1] - 48; // mCheck[0] = :A (10 17)
if (mCheck[n1].find(x1,0) == -1)//Square 0 can only go to 10,17
cout << "Invalid move in " << k1 << ": " << mCheck[n1] +
" and " << x1 << endl;
}
int aCheck[64] = {0}; //Check if each 0f 64 squares is stepped on once only
for (k1 = 0; k1 <= 63; k1++) // This is a frequency count
{
n1 = int(c1[k1]) - 48;
aCheck[n1] = aCheck[n1] + 1;
if (aCheck[n1] != 1) cout << " Error in " << k1 << endl;
}
}
void Save3() // Save all 64 tours in formatted form.
{
int k1, k2, k3,n1, n2,n3,aCount = -1, aMove[128], bMove[4096];
string x1,x2, x3,aShow[64], cMove[16];
char c1[128];
mTour = mTour + mTour; mTour.copy(c1, 128);
for (k1 = 0; k1 <= 127; k1++)
aMove[k1] = int(c1[k1]) - 48;
for (k2 = 0; k2 <= 63; k2++) // Start tours at 0-63
{
n1 = mTour.find(mNum[k2],0); x1 = "";
for (k1 = n1; k1 <= n1 + 63; k1++)
{
aCount++;
bMove[aCount] = aMove[k1];
}
}
//Following: lineup and formatting the 64 tours
aCount = -1; x1 = ""; //each section is 4 tours 16 * 4 = 64
for (k2 = 0; k2 <= 4032; k2+= 64)
{
for (k1 = 0; k1 <= 63; k1++)
{
n1 = k1 + k2; n2 = bMove[n1];
aShow[n2] = nNum[k1+1];
}
for (k1 = 0; k1 <= 63; k1++)
{
x1 = x1 + aShow[k1] + " ";
}
}
x2 = ""; n1 = -768;
for (k3 = 0; k3 <= 15; k3++) // There are 16 Tour Group. Each group has 4 tours
{
n1 = n1 + 768; // Each groups is 768 characters long (inc.spacing)
x2 = x1.substr(n1,768); x3 = "";
for (k2 = 0; k2 <= 168; k2+= 24)
{
for (k1 = 0; k1 <= 576; k1+= 192)
{
n3 = k2 + k1;
x3 = x3 + x2.substr(n3,24) + " ";
} // 3 spaces insert between 2 tours.
}
cMove[k3] = x3;
}
x2 = cMove[15];
ofstream OutFile("LineUp.txt", ios::out);
for (k2 = 0; k2 <= 15; k2++)
{
n1 = 0; x1 = cMove[k2];
for (k1 = 0; k1 <= 7; k1++)
{
OutFile << " " + x1.substr(n1,108) << endl; // Each row is 108 in length
n1 = n1 + 108;
}
OutFile << "" << endl;
}
OutFile.close();
}
void Show4()
{
int k1, k2, n1,aCount = -1;
string x1,x2;
char c1[64];
cout << " This is a chessboard." << endl;
x1 = "";
for (k1 = 0; k1 <= 63; k1++)
x1 = x1 + nNum[k1] + " ";
for (k1 = 0; k1 <= 224; k1+= 32)
cout << " " << x1.substr(k1,32) << endl;
cout << " Type a number(0-63) to start the knight tour: ";
cin >> n1;
cout << endl;
n1 = mTour.find(mNum[n1],0);
x1 = mTour + mTour;
mTour = x1.substr(n1,64);
mTour.copy(c1,64);
string aShow[64];
// Font must be Courier New or numbers won't line up.
for (k1 = 0; k1 <= 63; k1++)
{
n1 = int(c1[k1]) - 48;
aShow[n1] = nNum[k1+1] + " ";
}
x1 = "";
for (k1 = 0; k1 <= 63; k1++)
x1 = x1 + aShow[k1];
n1 = 0;
for (k1 = 0; k1 <= 7; k1++)
{
cout << " " + x1.substr(n1,32) << endl;
n1 = n1 + 32;
}
cout << endl;
}
***** 6
Print out 1440 Sudoku solutions
Program 1: Make a Down-Scaling Mode
When engineers were tasked to construct the Three-Gorges dam in China, They, within a building,
first built a dam, smaller but proportional to the real one. And later they scaling-up the mold
for the bigger one. I adopt this approach for printing out 1440 solutions for a difficult puzzle.
This is the mold (4*4*4; row,column & grid):
The Sudoku board (both integer and character representation):
0 1 2 3 a b c d
4 5 6 7 e f g h
8 9 1011 i j k l
1213 1415 m n o p (For permutation and joining purpose, use a-p to represent 0-15)
The puzzle: (_ means empty squares)
(Value and Position representation):
4 _ _ _ a _ _ _
_ 2 _ _ _ f _ _
_ _ 3 _ _ _ k _
_ _ _ 1 _ _ _ p
First I permutate a list of universal columns (good for all puzzles):
agjp agln ahjo ahkn bgip bglm bhio bhkm cejp celn cfip cflm dejo dekn dfio dfkm (16)
Next I sort the 16 by their in and out values:
For value 1, the columns must have an p and must not have a,f,k;
For value 2, the columns must have an f and must not have a,k,p;
For value 3, the columns must have an k and must not have a,f,p;
For value 4, the columns must have an a and must not have f,k,p;
Value Column
1 bgip cejp
2 cflm dfio
3 bhkm dekn
4 agln ahjo
Finally I join the 8 columns and get 2 solutions
1+2 = A: bgipcflm cejpdfio
A+3 = B: bgipcflmdekn cejpdfiodekn
B+4 = C: bgipcflmdeknahjo cejpdfiobhkmagln
bgip cflm dekn ahjo (first 4 chars are squares occupied by 1, 2nd 4, by 2, 3rd by 3, 4th by 4);
4123 3214 1432 2341
4 1 2 3
3 2 1 4
1 4 3 2
2 3 4 1
cejp dfio bhkm agln
4312 1243 2134 3421
4 3 1 2
1 2 4 3
2 1 3 4
3 4 2 1
How to decode the solutions
char c1[16];
string Show[16];
x1 = "bgipcflmdeknahjo",
x1.copy(c1,16);
x2 = "01234";
n1 = -1;
for (k2 = 1; k2 <= 4; k2++)
{
x1 = x2.substr(k2,1);
for (k1 = 1; k1 <= 4; k1++)
{
n1++;
n2 = int(c1[n1]) - 97; //a's ASCII value is 97 and is used as square 0; b's 98 ..
aShow[n2] = x1;
}
}
aShow[0-15) = "4312124321343421";
Program 1: Build the mode;
int mStart[5], mEnd[5], mLen;
string mNum[16],mPuz[16], mMove[16], mFile[] = {"F1.txt", "F2.txt"};
string mSu = "4000020000300001"; //The puzzle
void aMain();
void SetUp1();
void Col2();
void Col3();
void Join4(int);
void Show5();
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
SetUp1();
Col2();
Col3();
Join4(3);
Join4(4);
Show5();
}
void SetUp1()
{
int k1;
for (k1 = 0; k1 <= 15; k1++)
mNum[k1] = char(k1+97); // Use a-p to represent 0-15 squares
}
void Col2() // Permutate a list of universal puzzle columns;
{
int k1,k2, k3, k4,n1 = 3, n2, n3,Start1 = 0,End1, aCheck[16] = {0};;
string x1,x2, cIndex[16],gIndex[16], Index1, Index2,aMove[16],bMove[16];
char c1[4];
x1 = "0123012301230123"; x2 = "0011001122332233"; //x1: 15 squares's column values
for (k1 = 0; k1 <= 15; k1++) //x2: 15 squares's grid values
{
cIndex[k1] = x1.substr(k1,1);
gIndex[k1] = x2.substr(k1,1);
}
for (k1 = 0; k1 <= n1; k1++)
bMove[k1] = mNum[k1]; // Row 1 has 4 squares
for (k4 = 0; k4 <= 2; k4++) // Spin 4 times from Row1 to Row3
{
Start1 = Start1 + 4; // Row1: 0-3
End1 = n1; n1 = -1;
for (k3 = 0; k3 <= End1; k3++)
aMove[k3] = bMove[k3];
for (k3 = 0; k3 <= End1; k3++)
{
x1 = aMove[k3]; x1.copy(c1,k4+1);
for (k2 = 0; k2 <= k4; k2++)
{
n2 = int(c1[k2]) - 97; // change a-p to 0-15 to retrieve squares' values
Index1 = cIndex[n2]; Index2 = gIndex[n2];
for (k1 = Start1; k1 <= Start1 + 3; k1++)
{
if (Index1 == cIndex[k1] || Index2 == gIndex[k1])
aCheck[k1] = 1; // aCheck[] is an out-filter.
}
}
for (k2 = Start1; k2 <= Start1 + 3; k2++)
{
if (aCheck[k2] == 0)
{
n1++;
bMove[n1] = x1 + mNum[k2]; // If acheck[] is 0, pick it up
}
else
aCheck[k2] = 0; // Initialize the squares back to be available.
}
}
}
ofstream OutFile("15.txt",ios::out); //Universal columns: 16
for (k2 = 0; k2 <= n1; k2++)
OutFile << bMove[k2] << endl;
OutFile.close();
}
void Col3()
{
int k1,k2, k3,n1 = 3, n2, aLen, bLen,aEnd[5];
string x1,x2,x3,aPuz[16],aSu,aGet[5], aCut[5], aCol[16],bCol;
string aNum[] = {"0","1","2","3","4"}, bNum;
for (k1 = 0; k1 <= 15; k1++)
{
x1 = mSu.substr(k1,1);
if (x1 != "0")
{
x2 = x2 + mNum[k1];
aPuz[k1] = x1; //Load the puzzle to a 0-15 array, aPuz[]
}
}
for (k2 = 1; k2 <= 4; k2++)
{
bNum = aNum[k2];
x1 = ""; aSu = x2;
for (k1 = 0; k1 <= 15; k1++)
{
if (bNum == aPuz[k1])
{
x1 = x1 + mNum[k1];
n1 = x2.find(mNum[k1],0);
aSu.erase(n1,1);
}
}
aGet[k2] = x1; // I were a witness to a hit and run. My memory of the vehicle's license
aCut[k2] = aSu;// numbers: first digit: b; second digit is not h and not g.
} // so detectives filter in any liceses that have b. And then filter out
ifstream InFile("15.txt",ios::in); // those that have h or g. The supect list: 16.
for (k1 = 0; k1 <= 15; k1++) // aGet[] is for filter-in and aCut[] is for filter-out;
InFile >> aCol[k1];
InFile.close();
string aIndex[5]; n1 = -1;
for (k3 = 1; k3 <= 4; k3++)
{
x1 = aGet[k3]; aLen = x1.length(); //Filter-in usually have more than 1 character.
x2 = aCut[k3]; mStart[k3] = n1 + 1;
for (k2 = 0; k2 <= 15; k2++)
{
bCol = aCol[k2]; bLen = aLen;
for (k1 = 0; k1 <= 3; k1++)
{
aIndex[k1] = bCol.substr(k1,1);
n2 = x2.find(aIndex[k1],0);
if (n2 != -1) goto aSkip; //If a licese has a filter-out character, skip it
}
for (k1 = 0; k1 <= 3; k1++)
{
n2 = x1.find(aIndex[k1],0);
if (n2 != -1) bLen--; // We count all filter-in characters in a liceses.
} // If the numbers don't match, skip it.
if (bLen != 0) goto aSkip;
n1++;
mMove[n1] = bCol;
aSkip: k1 = 0;
}
mEnd[k3] = n1; // We use mStart[] and mEnd[] as indice to access the 16 suspects.
}
int Start2, End1, End2;
End1 = mEnd[1];
Start2 = mStart[2]; End2 = mEnd[2]; // Column 1 join column 2
n1 = -1; // Column 1 members pick up those of the column 2
// which have 4 diferent characters.
ofstream OutFile("F1.txt",ios::out);
for (k3 = 0; k3 <= End1; k3++)
{
x1 = mMove[k3];
for (k2 = 0; k2 <= 3; k2++)
aIndex[k2] = x1.substr(k2,1);
for (k2 = Start2; k2 <= End2; k2++)
{
x2 = mMove[k2];
for (k1 = 0; k1 <= 3; k1++)
{
x3 = x2.substr(k1,1);
if (x3 == aIndex[k1]) goto bSkip;
}
n1++;
OutFile << x1 + x2 << endl;
bSkip: k1 = 0;
}
}
mLen = n1; // the number of the suspects.
}
void Join4(int aNum) // Rotating operation. Open,load and process file 1 piece by piece
{ // and then save data into file 2. Next from file 2 to file 1
int k1,k2,k3,n1,n2, n3 = -1,aStart,aEnd;
string x1,x2, x3,aMove, bMove, aIndex[4];
string aFile, bFile;
aStart = mStart[aNum]; aEnd = mEnd[aNum];
n1 = 1 - (aNum % 2); n2 = 1 - n1; // Rotate file 1 to file 2. file 2 to file 1
aFile = mFile[n1]; bFile = mFile[n2];
ifstream InFile(aFile.c_str(), ios::in);
ofstream OutFile(bFile.c_str(),ios::out);
for (k3 = 0; k3 <= mLen; k3++)
{
InFile >> aMove; n1 = -1;
for (k2 = 0; k2 <= 3; k2++)
aIndex[k2] = "";
for (k2 = 0; k2 <= 1; k2++)
{
for (k1 = 0; k1 <= 3; k1++)
{
n1++;
aIndex[k1] = aIndex[k1] + aMove.substr(n1,1);
}
}
for (k2 = aStart; k2 <= aEnd; k2++)
{
x1 = mMove[k2];
for (k1 = 0; k1 <= 3; k1++)
{
x2 = x1.substr(k1,1); n2 = aIndex[k1].find(x2,0);
if (n2 != -1) goto aSkip;
}
n3++;
bMove = aMove + x1;
OutFile << bMove << endl;
aSkip: k1 = 0;
}
}
InFile.close();
OutFile.close();
mLen = n3;
}
void Show5() //Print 2 solutions onscreen and in a text file
{
int k1,k2,k3,n1 = -1,n2;
string x1,x2, x3,aMove[2], bMove, aShow[16], aNum = "01234";
char c1[16];
ifstream InFile("F1.txt",ios::in);
InFile >> aMove[0];
InFile >> aMove[1];
InFile.close();
ofstream OutFile("2Keys.txt",ios::out);
for (k3 = 0; k3 <= 1; k3++)
{
bMove = aMove[k3];
cout << bMove << endl;
OutFile << bMove << endl;
bMove.copy(c1,16); n1 = -1;
for (k2 = 1; k2 <= 4; k2++)
{
x1 = aNum.substr(k2,1);
for (k1 = 1; k1 <= 4; k1++)
{
n1++;
n2 = int(c1[n1]) - 97;
aShow[n2] = x1;
}
}
x2 = "";
for (k2 = 0; k2 <= 15; k2++)
x2 = x2 + aShow[k2];
cout << x2 << endl;
OutFile << x2 << endl;
n1 = -1;
for (k2 = 1; k2 <= 4; k2++)
{
x3 = "";
for (k1 = 1; k1 <= 4; k1++)
{
n1++;
cout << aShow[n1] + " ";
x3 = x3 + aShow[n1] + " ";
if (k1 % 2 == 0) cout << " ";
if (k1 % 2 == 0) x3 = x3 + " ";
}
cout << endl; OutFile << x3 << endl;
if (k2 % 2 == 0) cout << endl;
if (k2 % 2 == 0) OutFile << endl;
}
}
OutFile.close();
}
Program 2: Print out 1440 solutions from a difficult Sudoku.
Up-scaling the mode above (from 4*4*4 game board to 9*9*9 Sudoku board).
This program first permutates a list of the universal columns (46656), and filter in and out
a list of value-specific (1-9) columns (848). Finally I join all 9 columns into full solutions.
The joining operation gets an array more than half million long which exceeds the compiler's
memory limit of a quarter of million. So, I overcome that limit by piece-by-piece data processing.
That means loading up one piece data, processing it and saving the data into a text file.
It also means opening file 1 and saving into file 2, and Opening file 2 and saving into file 1.
Making 7 rotations to get 1440 soluions. Each solution is 81 in length.
Data Representation (9*9*9: Row,Column,Grid):
1. Sudokuboard
Integer ASCII
0 1 2 3 4 5 6 7 8 . / 0 1 2 3 4 5 6
9 10 11 12 13 14 15 16 17 7 8 9 : ; < = > ?
18 19 20 21 22 23 24 25 26 @ A B C D E F G H
27 28 29 30 31 32 33 34 35 I J K L M N O P Q
36 37 38 39 40 41 42 43 44 R S T U V W X Y Z
45 46 47 48 49 50 51 52 53 [ \ ] ^ _ ` a b c
54 55 56 57 58 59 60 61 62 d e f g h i j k l
63 64 65 66 67 68 69 70 71 m n o p q r s t u
72 73 74 75 76 77 78 79 80 v w x y z { | } ~
(Notice: I use ASCII 0 to represent 2, and 1 to 3)
Unit Values:
Row Column Grid
000 000 000 012 345 678 000 111 222
111 111 111 012 345 678 000 111 222
222 222 222 012 345 678 000 111 222
333 333 333 012 345 678 333 444 555
444 444 444 012 345 678 333 444 555
555 555 555 012 345 678 333 444 555
666 666 666 012 345 678 666 777 888
777 777 777 012 345 678 666 777 888
888 888 888 012 345 678 666 777 888
How to permutate for the solutions?
Follow the rule (In each unit, the same number (1-9) much not shows up more than once)
That means A can picks up the cells that have different column and grid values.
Suppose we start with .(cell 0),
Cell 0's Column value is 0 and its Grid value is 0.
We start with row 2. . becomes .: .; .< .= .> .? (6 moves from row 2)
Row by row, until we finish row 9.
Proceed to Row 2. We get .:F .:G .:H etc (for row 3)
2. The Puzzle (0 represents empty squares)
000008009050090000009004800002140003006000900400067100005900300000030070800400000
Value-base Representation Position-based Representation
_ _ _ _ _ 8 _ _ 9 _ _ _ _ _ 3 _ _ 6 (3 means cell 5, 6, 8)
_ 5 _ _ 9 _ _ _ _ _ 8 _ _ ; _ _ _ _
_ _ 9 _ _ 4 8 _ _ _ _ B _ _ E F _ _
_ _ 2 1 4 _ _ _ 3 _ _ K L M _ _ _ Q
_ _ 6 _ _ _ 9 _ _ _ _ T _ _ _ X _ _
4 _ _ _ 6 7 1 _ _ [ _ _ _ * _ a _ _ (* means cell 49)
_ _ 5 9 _ _ 3 _ _ _ _ f g _ _ j _ _
_ _ _ _ 3 _ _ 7 _ _ _ _ _ q _ _ t _
8 _ _ 4 _ _ _ _ _ v _ _ y _ _ _ _ _
// mSu below, a Sudoku puzzle, from the book "(Wei-Meng Lee, Programming Sudoku, page 169)"
// In the book, the author states that he does not know if that puzzle is single-solution
// puzzle. Since Sudoku in Japanese means single solution. The book should be better titled
// Programming Possible Sudoku.
// Mr Lee uses 3-dimention array to represent the Soduku board (row,column and grid). I use
// one-dimention array with cross-reference indice to represent the board.
// Index Length: 242
// Unit Type Index number Cross-reference number
// Row 0-80 0-80
// Column 81-161 0,9,18, ...
// Grid 162-242 0,1,2,9,10,11...
int mLen, mStart[10], mEnd[10]; //represent a puzzle. I use all 95 non-functional keys in
// a PC's keyboard to represent a puzzle. Those keys happens to be consecutive valued.
string mSu =
"000008009050090000009004800002140003006000900400067100005900300000030070800400000";
// 0 represents empty squares to be filled in by the puzzle solvers. Total 81 characters.
string mKey =
"324718659758693412619524837582149763176385924493267185265971348941832576837456291";
string mNum[81], mPuz[81],mMove[849], mFile[] = {"F2.txt","F1.txt"};
// mFile are Rotational files: Open, load and chop A and save to B. And then reverse order.
void aMain();
void SetUp1();
void GetCol2();
void GetCol3();
void Join4(int);
void Check5();
void Show6();
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
int k1;
SetUp1();
GetCol2();
cout << "Joining Operations (1440 solutions); compiling time: 79 seconds." << endl;
cout << "After Valued 1 picks up Valued 2, rotation starts" << endl;
cout << "Combination picks up 3,4,5,6,7,8,9 (7 rotations get 7 array sizes" << endl;
GetCol3();
for (k1 = 3; k1 <= 9; k1++) // Column 1 + 2 picks 3,4,5,6,7,8,9
Join4(k1);
Check5();
cout << "Print the first solution" << endl;
Show6();
}
void SetUp1()
{
int k1,k2, n1,n2,aLen[10], bLen[10];
string x1,x2, aNum, bNum, aGet[10], aCut[10];
for (k1 = 0; k1 <= 80; k1++)
mNum[k1] = char(k1+46);
for (k1 = 0; k1 <= 80; k1++)
{
x1 = mSu.substr(k1,1);
if (x1 == "0")
x1 = "";
else
aNum = aNum + mNum[k1];
mPuz[k1] = x1;
}
for (k2 = 3; k2 <= 11; k2++) //mNum[3-11]: 1-9 characters.
{
x1 = mNum[k2]; x2 = "";
for (k1 = 0; k1 <= 80; k1++)
{
if (x1 == mPuz[k1]) x2 = x2 + mNum[k1];
}
aGet[k2-2] = x2; aLen[k2 - 2] = x2.length() -1;
}
for (k2 = 3; k2 <= 11; k2++)
{
x1 = mNum[k2]; bNum = aNum;
for (k1 = 0; k1 <= 80; k1++)
{
if (x1 == mPuz[k1])
{
n1 = bNum.find(mNum[k1],0);
if (n1 != -1) bNum.erase(n1,1);
}
}
aCut[k2 - 2] = bNum; bLen[k2 - 2] = bNum.length() - 1;
}
ofstream OutFile("GetCut1.txt",ios::out);
for (k1 = 1; k1 <= 9; k1++)
OutFile << aGet[k1] << endl;
for (k1 = 1; k1 <= 9; k1++)
OutFile << aCut[k1] << endl;
for (k1 = 1; k1 <= 9; k1++)
OutFile << aLen[k1] << endl;
for (k1 = 1; k1 <= 9; k1++)
OutFile << bLen[k1] << endl;
OutFile << "1-9.must.have-list" << endl;
OutFile << "1-9.must.not-have-list" << endl;
OutFile.close();
}
void GetCol2()
{
int k1,k2, k3,k4,n1,n2, aEnd, bStart = 9, bEnd,Index1[81] = {0};
string x1,x2,aNum, aIndex[81],bIndex[81], aMove[46656], bMove[46656];
string y1 =
"000111222000111222000111222333444555333444555333444555666777888666777888666777888";
char c1[81];
x2 = "";
for (k2 = 0; k2 <= 8; k2++)
{
x1 = mNum[k2+ 2]; n1 = k2;
for (k1 = 0; k1 <= 8; k1++)
{
aIndex[n1] = x1;
n1 = n1 + 9;
}
}
for (k1 = 0; k1 <= 80; k1++)
bIndex[k1] = y1.substr(k1,1);
n2 = -1;
for (k2 = 0; k2 <= 8; k2++)
{
aNum = mNum[k2];
x1 = aIndex[k2]; x2 = bIndex[k2];
for (k1 = 9; k1 <= 17; k1++)
{
if (x1 != aIndex[k1] && x2 != bIndex[k1])
{
n2++; bMove[n2] = aNum + mNum[k1];
}
}
}
for (k4 = 2; k4 <= 8; k4++)
{
aEnd = n2;
for (k3 = 0; k3 <= aEnd; k3++)
aMove[k3] = bMove[k3];
bStart = bStart + 9; bEnd = bStart + 8;
n2 = -1;
for (k3 = 0; k3 <= aEnd; k3++)
{
aNum = aMove[k3]; aNum.copy(c1,k4);
for (k2 = 0; k2 < k4; k2++)
{
n1 = int(c1[k2]) - 46;
x1 = aIndex[n1]; x2 = bIndex[n1];
for (k1 = bStart; k1 <= bEnd; k1++)
if (x1 == aIndex[k1] || x2 == bIndex[k1]) Index1[k1] = 1;
}
for (k2 = bStart; k2 <= bEnd; k2++)
{
if (Index1[k2] == 0)
{
n2++; bMove[n2] = aNum + mNum[k2];
}
else
Index1[k2] = 0;
}
}
}
ofstream OutFile("46655.txt",ios::out);
for (k1 = 0; k1 <= n2; k1++)
OutFile << bMove[k1] << endl;
OutFile.close();
}
void GetCol3()
{
int k1,k2, k3,n1,n2, n3 = -1,aStart,aEnd, bStart,bEnd,End1[10];
string x1,x2,x3,Get1[10],aGet,Cut1[10],aCut,aMove[46656], aIndex[81];
ifstream InFile("46655.txt",ios::in); //46655 is the universal column count
for (k1 = 0; k1 <= 46655; k1++) // From this count, you filter douwn to 848
InFile >> aMove[k1]; // in 9 columns. Valued 1 column gets 190
InFile.close(); // but valued 9 column gets only 1.
ifstream aInFile("GetCut1.txt",ios::in); // In the puzzle, number 1 shows up in
for (k1 = 1; k1 <= 9; k1++) // square L and a (30, 51); number 8 shows
aInFile >> Get1[k1]; // in square 5 and number 9 shows up in 8.
for (k1 = 1; k1 <= 9; k1++)
aInFile >> Cut1[k1];
n3 = -1;
for (k3 = 1; k3 <= 9; k3++)
{
mStart[k3] = n3 + 1;
aGet = Get1[k3]; aEnd = aGet.length();
aCut = Cut1[k3];
for (k2 = 0; k2 <= 46655; k2++)
{
x1 = aMove[k2];n2 = aEnd;
for (k1 = 0; k1 <= 8; k1++)
{
x2 = x1.substr(k1,1);
n1 = aCut.find(x2,0);
if (n1!= -1) goto aSkip;
}
for (k1 = 0; k1 <= 8; k1++)
{
x2 = x1.substr(k1,1);
n1 = aGet.find(x2,0);
if (n1!= -1) n2--;
}
if (n2 != 0) goto aSkip;
n3++;
mMove[n3] = x1;
aSkip: k1 = 0; //xxxx: must be followed by xx = yy; : to ; or it won't compile.
}
mEnd[k3] = n3; //Cross-reference mStart and mEnd helps you access any column
} //e.g. For column 1, mStart[1] = 0; mEnd[1] = 109
// To access column 1: for k1 = 0 to 109
n1 = -1;
aStart = mStart[1]; aEnd = mEnd[1];
bStart = mStart[2]; bEnd = mEnd[2];
ofstream OutFile("F1.txt",ios::out);
for (k3 = aStart; k3 <= aEnd; k3++)
{
x1 = mMove[k3];
for (k2 = 0; k2 <= 8; k2++)
aIndex[k2] = x1.substr(k2,1);
for (k2 = bStart; k2 <= bEnd; k2++)
{
x2 = mMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
x3 = x2.substr(k1,1);
if (x3 == aIndex[k1]) goto Skip;
}
n1++;
x3 = x1 + x2;
OutFile << x3 << endl;
Skip: k1 = 0;
}
}
OutFile.close();
mLen = n1;
cout << mLen << endl;
}
void Join4(int pLen) // Column 1 joints 2, ... 9
{
int k1,k2,k3,n1,n2,aStart,bStart,aEnd,bEnd;
string x1,x2,x3, aFile,bFile,aIndex[81];
bStart = mStart[pLen]; bEnd = mEnd[pLen];
n1 = pLen % 2; n2 = 1 - n1;
aFile = mFile[n1]; bFile = mFile[n2];
ifstream InFile1(aFile.c_str(),ios::in);
ofstream OutFile1(bFile.c_str(),ios::out);
aEnd = mLen;
n2 = -1;
for (k3 = 0; k3 <= aEnd; k3++)
{
InFile1 >> x1;
for (k2 = 0; k2 <= 8; k2++)
aIndex[k2] = "";
n1 = -1;
for (k2 = 2; k2 <= pLen; k2++)
{
for (k1 = 0; k1 <= 8; k1++)
{
n1++;
aIndex[k1] = aIndex[k1] + x1.substr(n1,1);
}
}
for (k2 = bStart; k2 <= bEnd; k2++)
{
x2 = mMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
x3 = x2.substr(k1,1);
n1 = aIndex[k1].find(x3,0);
if (n1 != -1) goto Skip1; // a square can't be occupied twice
} // So skipping occurrs
n2++;
x3 = x1 + x2;
OutFile1 << x3 << endl;
Skip1: k1 = 0;
}
}
OutFile1.close();
InFile1.close();
mLen = n2;
cout << mLen << endl; // The highest number in a file is 640K
}
void Check5() // 5 checks: within 1441 solutions (keys), any duplicates?; same number
{ //of 1 or 2... shows up more than once in the row, colum or grid.
// All solutions come from the same puzzle. The solution from the book shows up.
int k1,k2, k3,n1,n2, n3, Index1[81], Index2[81], Index3[81],bIndex[81];
string x1,x2,x3,aKey[1441],bKey[81], aIndex[81];
char c1[81];
ifstream InFile("F2.txt",ios::in); // Change position-based keys into value-based ones.
for (k3 = 0; k3 <= 1440; k3++)
{
InFile >> x1;
x1.copy(c1,81); //Change string into integer which are used to retrieve values of R & C
for (k2 = 0; k2 <= 80; k2++)
bIndex[k2] = int(c1[k2]) - 46; // ASCII valued 46 is used as 0.
n1 = -1;
for (k2 = 3; k2 <= 11; k2++)
{
x1 = mNum[k2];
for (k1 = 1; k1 <= 9; k1++)
{
n1++;
n2 = bIndex[n1]; bKey[n2] = x1;
}
}
x1 = "";
for (k2 = 0; k2 <= 80; k2++)
x1 = x1 + bKey[k2];
aKey[k3] = x1;
}
InFile.close();
ofstream OutFile("1440.txt", ios::out); // Sort the 1440 keys
for (k2 = 0; k2 <= 1440; k2++)
{
x1 = aKey[k2];
for (k1 = k2 + 1; k1<= 1440; k1++)
{
if (x1 > aKey[k1])
{
x2 = x1; x1 = aKey[k1]; aKey[k1] = x2;
}
}
aKey[k2] = x1;
OutFile << x1 << endl;
}
OutFile.close();
x1 = "000111222000111222000111222333444555333444555333444555666777888666777888666777888";
x1.copy(c1,81); // x1 is the grid values.
n1 = -1; // Each square has 3 values(0-8): row, column and grid.
for (k1 = 0; k1 <= 80; k1++)
{
aIndex[k1] = mKey.substr(k1,1); // mKey is the key by the author
Index1[k1] = k1 / 9; // Row value 0-8
n1 = (n1 + 1) % 9;
Index2[k1] = n1; // Column value 0-8
Index3[k1] = int(c1[k1]) - 48;//Grid value 000 111 222 ...
}
Index2[80] = 8; //3 checks mean insert 3 wrong data and errors must be picked up
for (k3 = 0; k3 <= 1440; k3++) // Same value must not show up more than once
{ // in the same row, column or grid.
x1 = aKey[k3]; //if (k3 == 1440) x1 = x1.substr(0,80) + "2"; Failure test.
for (k2 = 0; k2 <= 80; k2++)
aIndex[k2] = x1.substr(k2,1);
for (k2 = 0; k2 <= 79; k2++)
{
x1 = aIndex[k2];
n1 = Index1[k2]; n2 = Index2[k2]; n3 = Index3[k2];
for (k1 = k2 + 1; k1 <= 80;k1++)
{
if (n1 == Index1[k1] || n2 == Index2[k1] || n3 == Index3[k1])
{
if (x1 == aIndex[k1])
{
cout << "Value conflict " << k3 << endl;
goto Skip1;
}
}
}
Skip1: k1 = 0;
}
}
x1 = aKey[0];// aKey[1439] = aKey[1440]; Unblock this to insert an error for failure check
for (k1 = 1; k1 <= 1440; k1++) //All 0-1440 keys must be unique
{
x2 = aKey[k1];
if (x1 == x2) cout << "Duplicate in " << k1 -1 << " and " << k1 << endl;
x1 = x2;
}
for (k2 = 0; k2 <= 1440; k2++)
{
x1 = aKey[k2];
// if (k2 == 1440) x1 = x1.substr(0,75) + "300000"; //Failure check
for (k1 = 0; k1 <= 80; k1++)
{
x3 = mPuz[k1];
if (x3 != "" )
{
x2 = x1.substr(k1,1);
if (x2 != x3)
{
cout << "Solution " << k2 << " does not match the puzzle " << endl;
goto aSkip;
}
}
}
aSkip: k1 = 0;
}
for (k1 = 0; k1 <= 1440; k1++)
if (aKey[k1] == mKey) break;
cout << "Solution provided by the author is in the array element of " << k1 << endl;
}
void Show6() // A solution is 81 ASCII characters.The first 9 char are the positions of
{ // 1 and the next 9 are the 2 ...9
int k1,k2,n1,n2,aIndex[81];
string x1, aShow[81], aSpace = " ";
char c1[81];
ifstream InFile("F2.txt",ios::in); //Display the first solution in a formatted way
InFile >> x1;
InFile.close();
x1.copy(c1,81); n1 = -1;
for (k1 = 0; k1 <= 80; k1++)
aIndex[k1] = int(c1[k1]) - 46;
for (k2 = 3; k2 <= 11; k2++)
{
x1 = mNum[k2]; // number 1 to 9
for (k1 = 0; k1 <= 8; k1++)
{
n1++;
n2 = aIndex[n1]; //aIndex are the numbers of cells (0-80)
aShow[n2] = x1;
}
}
n1 = -1; x1 = "";
for (k2 = 0; k2 <= 72; k2+= 9)
{
for (k1= k2; k1 <= k2 + 8; k1++)
{
x1 = x1 + aShow[k1] + " ";
if ((k1 + 1) % 3 == 0) x1 = x1 + " ";
}
if (k2 == 18 || k2 == 45) x1 = x1 + aSpace;
}
n1 = -21;
for (k1 = 1; k1 <= 11; k1++)
{
n1 = n1 + 21; //A line of puzzle is 21 in length.
cout << x1.substr(n1,21) << endl;
}
}
Program 3 (Sudoku);
// m1 below is the world's most difficult sudoku puzze (according to a google search)
int mLen, mStart[10], mEnd[10];// Compiling time: 45 seconds
string m1 =
"800000000003600000070090200050007000000045700000100030001000068008500010090000400";
string mKey =
"812753649943682175675491283154237896369845721287169534521974368438526917796318452";
string mNum[81], mPuz[81],mMove[674], mFile[] = {"F2.txt","F1.txt"};
void aMain();
void SetUp1();
void GetCol2();
void GetCol3();
void Join4(int);
void Show5();
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
int k1;
SetUp1();
GetCol2();
GetCol3();
for (k1 = 3; k1 <= 9; k1++)
Join4(k1);
Show5();
}
void SetUp1()
{
int k1,k2, n1,n2;
string x1,x2, aNum, bNum, aGet[10], aCut[10];
for (k1 = 0; k1 <= 80; k1++)
mNum[k1] = char(k1+46);
for (k1 = 0; k1 <= 80; k1++)
{
x1 = m1.substr(k1,1);
if (x1 == "0")
x1 = "";
else
aNum = aNum + mNum[k1];
mPuz[k1] = x1;
}
for (k2 = 3; k2 <= 11; k2++)
{
x1 = mNum[k2]; x2 = "";
for (k1 = 0; k1 <= 80; k1++)
{
if (x1 == mPuz[k1]) x2 = x2 + mNum[k1];
}
aGet[k2 -2] = x2;
}
for (k2 = 3; k2 <= 11; k2++)
{
x1 = mNum[k2]; bNum = aNum;
for (k1 = 0; k1 <= 80; k1++)
{
if (x1 == mPuz[k1])
{
n1 = bNum.find(mNum[k1],0);
if (n1 != -1) bNum.erase(n1,1);
}
}
aCut[k2 - 2] = bNum;
}
ofstream OutFile("GetCut2.txt",ios::out);
for (k1 = 1; k1 <= 9; k1++)
OutFile << aGet[k1] << endl;
for (k1 = 1; k1 <= 9; k1++)
OutFile << aCut[k1] << endl;
OutFile << "1-9.must.have-list" << endl;
OutFile << "1-9.must.not-have-list" << endl;
OutFile.close();
}
void GetCol2()
{
int k1,k2, k3,k4,n1,n2, aEnd, bStart = 9, bEnd,Index1[81] = {0};
string x1,x2,aNum, cIndex[81],gIndex[81], aMove[46656], bMove[46656];
string y1 =
"000111222000111222000111222333444555333444555333444555666777888666777888666777888";
char c1[81];
n1 = -1;
for (k1 = 0; k1 <= 80; k1++)
{
n1 = (n1 + 1) % 9;
cIndex[k1] = mNum[n1 + 2];
}
for (k1 = 0; k1 <= 80; k1++)
gIndex[k1] = y1.substr(k1,1);
n2 = -1;
for (k2 = 0; k2 <= 8; k2++)
{
aNum = mNum[k2];
x1 = cIndex[k2]; x2 = gIndex[k2];
for (k1 = 9; k1 <= 17; k1++)
{
if (x1 != cIndex[k1] && x2 != gIndex[k1])
{
n2++; bMove[n2] = aNum + mNum[k1];
}
}
}
for (k4 = 2; k4 <= 8; k4++)
{
aEnd = n2;
for (k3 = 0; k3 <= aEnd; k3++)
aMove[k3] = bMove[k3];
bStart = bStart + 9; bEnd = bStart + 8;
n2 = -1;
for (k3 = 0; k3 <= aEnd; k3++)
{
aNum = aMove[k3]; aNum.copy(c1,k4); //cout << aNum << endl;
for (k2 = 0; k2 < k4; k2++)
{
n1 = int(c1[k2]) - 46;
x1 = cIndex[n1]; x2 = gIndex[n1];
for (k1 = bStart; k1 <= bEnd; k1++)
if (x1 == cIndex[k1] || x2 == gIndex[k1])
Index1[k1] = 1;
}
for (k2 = bStart; k2 <= bEnd; k2++)
{
if (Index1[k2] == 0)
{
n2++; bMove[n2] = aNum + mNum[k2];
}
else
Index1[k2] = 0;
}
}
}
ofstream OutFile("46655.txt",ios::out);
for (k1 = 0; k1 <= n2; k1++)
OutFile << bMove[k1] << endl;
OutFile.close();
}
void GetCol3()
{
int k1,k2, k3,n1,n2, n3 = -1,aStart,aEnd, bStart,bEnd,End1[10];
string x1,x2,x3,Get1[10],aGet,bGet[10],Cut1[10],aCut,bCut[99];
string aMove[46656], aIndex[81];
ifstream InFile("46655.txt",ios::in);
for (k1 = 0; k1 <= 46655; k1++)
InFile >> aMove[k1];
InFile.close();
ifstream aInFile("GetCut2.txt",ios::in);
for (k1 = 1; k1 <= 9; k1++)
aInFile >> Get1[k1];
for (k1 = 1; k1 <= 9; k1++)
aInFile >> Cut1[k1];
aInFile.close();
n3 = -1;
for (k3 = 1; k3 <= 9; k3++)
{
mStart[k3] = n3 + 1;
aGet = Get1[k3]; aEnd = aGet.length();
aCut = Cut1[k3];
for (k2 = 0; k2 <= 46655; k2++)
{
x1 = aMove[k2];n2 = aEnd;
for (k1 = 0; k1 <= 8; k1++)
{
x2 = x1.substr(k1,1);
n1 = aCut.find(x2,0);
if (n1!= -1) goto aSkip;
}
for (k1 = 0; k1 <= 8; k1++)
{
x2 = x1.substr(k1,1);
n1 = aGet.find(x2,0);
if (n1!= -1) n2--;
}
if (n2 != 0) goto aSkip;
n3++;
mMove[n3] = x1;
aSkip: k1 = 0;
}
mEnd[k3] = n3; //Cross-reference mStart and mEnd helps you access any column
}
n2 = -1;
aStart = mStart[1]; aEnd = mEnd[1];
bStart = mStart[2]; bEnd = mEnd[2];
ofstream OutFile("F1.txt",ios::out);
for (k3 = aStart; k3 <= aEnd; k3++)
{
x1 = mMove[k3];
for (k2 = 0; k2 <= 8; k2++)
aIndex[k2] = "";
n1 = -1;
for (k2 = 0; k2 <= 0; k2++)
{
for (k1 = 0; k1 <= 8; k1++)
{
n1++;
aIndex[k1] = aIndex[k1] + x1.substr(n1,1);
}
}
for (k2 = bStart; k2 <= bEnd; k2++)
{
x2 = mMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
x3 = x2.substr(k1,1);
n1 = aIndex[k1].find(x3,0);
if (n1 != -1) goto Skip;
}
n2++;
x3 = x1 + x2;
OutFile << x3 << endl;
Skip: k1 = 0;
}
}
OutFile.close();
mLen = n2;
cout << mLen << endl;
}
void Join4(int pLen)
{
int k1,k2,k3,n1,n2,bStart,aEnd,bEnd;
string x1,x2,x3, aFile,bFile,aIndex[81];
bStart = mStart[pLen]; bEnd = mEnd[pLen];
n1 = pLen % 2; n2 = 1 - n1;
aFile = mFile[n1]; bFile = mFile[n2];
ifstream InFile1(aFile.c_str(),ios::in);
ofstream OutFile1(bFile.c_str(),ios::out);
aEnd = mLen;
n2 = -1;
for (k3 = 0; k3 <= aEnd; k3++)
{
InFile1 >> x1;
for (k2 = 0; k2 <= 8; k2++)
aIndex[k2] = "";
n1 = -1;
for (k2 = 2; k2 <= pLen; k2++)
{
for (k1 = 0; k1 <= 8; k1++)
{
n1++;
aIndex[k1] = aIndex[k1] + x1.substr(n1,1);
}
}
for (k2 = bStart; k2 <= bEnd; k2++)
{
x2 = mMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
x3 = x2.substr(k1,1);
n1 = aIndex[k1].find(x3,0);
if (n1 != -1) goto Skip1;
}
n2++;
x3 = x1 + x2;
OutFile1 << x3 << endl;
Skip1: k1 = 0;
}
}
OutFile1.close();
InFile1.close();
mLen = n2;
cout << mLen << endl;
}
void Show5()
{
int k1,k2,n1,n2, aIndex[81];
string x1,aShow[81],aSpace = " ";
char c1[81];
ifstream InFile("F2.txt",ios::in);
InFile >> x1;
InFile.close();
x1.copy(c1,81); n1 = -1;
for (k1 = 0; k1 <= 80; k1++)
aIndex[k1] = int(c1[k1]) - 46;
for (k2 = 3; k2 <= 11; k2++)
{
x1 = mNum[k2];
for (k1 = 0; k1 <= 8; k1++)
{
n1++;
n2 = aIndex[n1];
aShow[n2] = x1;
}
}
n1 = -1; x1 = "";
for (k2 = 0; k2 <= 72; k2+= 9)
{
for (k1= k2; k1 <= k2 + 8; k1++)
{
x1 = x1 + aShow[k1] + " ";
if ((k1 + 1) % 3 == 0) x1 = x1 + " ";
}
if (k2 == 18 || k2 == 45 || k2 == 72) x1 = x1 + aSpace;
}
n1 = -21;
for (k1 = 1; k1 <= 12; k1++)
{
n1 = n1 + 21;
cout << x1.substr(n1,21) << endl;
}
}
Program 4 (Sudoku):
This program prints out solutions for 4 puzzles
void aMain();
void SetUp1();
void Load2(int);
void GetCol3();
void Join4(int);
int mStart[10], mEnd[10], mLen;
string mNum[81], mCol[46656],mPuz[81],mMove[9999],mSu[] =
{"006074120002081460194263875629305700057006390301790650913657200005000936268439517",
"006500700090040050500030006700003000043000690000200007100050008030080040002000900",
"700300008006050090021008000200003600070090050004600003000200140040060200100005009",
"080000006300009000000670085032060000700803002000020650940032000000400007600000030"};
// Puzzle 1: Wei-Meng Lee, Programming Sudoku, page 103-105
// Puzzle 4: Only 23456789 show up in the puzzle. WebSudoku.com: 4,741,795,069)
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
int k1;
ofstream OutFile("Sudo4S.txt",ios::out); //Print an empty file before 4 appendings.
OutFile.close();
SetUp1();
for (k1 = 0; k1 <= 3; k1++)
{
Load2(k1);
GetCol3();
Join4(k1);
}
cout << "Go to Sudo4S.txt for all 4 puzzles' solutions" << endl;
}
void SetUp1()
{
int k1;
for (k1 = 0; k1 <= 80; k1++)
mNum[k1] = char(k1+46);
ifstream InFile("46655.txt",ios::in);
for (k1 = 0; k1 <= 46655; k1++)
InFile >> mCol[k1];
InFile.close();
}
void Load2(int pNum)
{
int k1,k2, n1,n2,aLen[10], bLen[10];
string x1,x2, aPuz,aNum, bNum, aGet[10], aCut[10];
aPuz = mSu[pNum];
for (k1 = 0; k1 <= 80; k1++)
{
x1 = aPuz.substr(k1,1);
if (x1 == "0")
x1 = "";
else
aNum = aNum + mNum[k1];
mPuz[k1] = x1;
}
for (k2 = 3; k2 <= 11; k2++)
{
x1 = mNum[k2]; x2 = "";
for (k1 = 0; k1 <= 80; k1++)
{
if (x1 == mPuz[k1]) x2 = x2 + mNum[k1];
}
aGet[k2 - 2] = x2; aLen[k2 - 2] = x2.length() -1;
}
for (k2 = 3; k2 <= 11; k2++)
{
x1 = mNum[k2]; bNum = aNum;
for (k1 = 0; k1 <= 80; k1++)
{
if (x1 == mPuz[k1])
{
n1 = bNum.find(mNum[k1],0);
if (n1 != -1) bNum.erase(n1,1);
}
}
aCut[k2 - 2] = bNum; bLen[k2 - 2] = bNum.length() - 1;
}
ofstream OutFile("GetCut3.txt",ios::out);
for (k1 = 1; k1 <= 9; k1++)
OutFile << aGet[k1] << endl;
for (k1 = 1; k1 <= 9; k1++)
OutFile << aCut[k1] << endl;
for (k1 = 1; k1 <= 9; k1++)
OutFile << aLen[k1] << endl;
for (k1 = 1; k1 <= 9; k1++)
OutFile << bLen[k1] << endl;
OutFile << "1-9.must.have-list" << endl;
OutFile << "1-9.must.not-have-list" << endl;
OutFile << "1-9.have-list.length" << endl;
OutFile << "1-9.not.have-list.length" << endl;
OutFile.close();
}
void GetCol3()
{
int k1,k2, k3,n1,n2, n3 = -1,aStart,aEnd, bStart,bEnd,aLen[10], bLen[10];
string x1,x2,x3,Get1[10],aGet,bGet[10],Cut1[10],aCut,bCut[99],aMove[46656];
ifstream InFile("46655.txt",ios::in);
for (k1 = 0; k1 <= 46655; k1++)
InFile >> aMove[k1];
InFile.close();
ifstream aInFile("GetCut3.txt",ios::in);
for (k1 = 1; k1 <= 9; k1++)
getline(aInFile,Get1[k1]);
for (k1 = 1; k1 <= 9; k1++)
getline(aInFile,Cut1[k1]);
for (k1 = 1; k1 <= 9; k1++)
{
getline(aInFile,x1);
aLen[k1] = atoi(x1.c_str());
}
for (k1 = 1; k1 <= 9; k1++)
{
getline(aInFile,x1);
bLen[k1] = atoi(x1.c_str());
}
aInFile.close();
n3 = -1;
for (k3 = 1; k3 <= 9; k3++)
{
mStart[k3] = n3 + 1;
aGet = Get1[k3]; aEnd = aGet.length();
aCut = Cut1[k3];
for (k2 = 0; k2 <= 46655; k2++)
{
x1 = aMove[k2];n2 = aEnd;
for (k1 = 0; k1 <= 8; k1++)
{
x2 = x1.substr(k1,1);
n1 = aCut.find(x2,0);
if (n1!= -1) goto aSkip;
}
for (k1 = 0; k1 <= 8; k1++)
{
x2 = x1.substr(k1,1);
n1 = aGet.find(x2,0);
if (n1!= -1) n2--;
}
if (n2 != 0) goto aSkip;
n3++;
mMove[n3] = x1;
aSkip: k1 = 0;
}
mEnd[k3] = n3; //Cross-reference mStart and mEnd helps you access any column
}
}
void Join4(int pNum)
{
int k1,k2,k3,k4, n1,n2,n3,bStart,aEnd,bEnd;
string x1,x2,x3, aMove[14300], bMove[14300], aCol[9];
int n4 = 0;
n1 = mEnd[1];
for (k1 = 0; k1 <= n1; k1++)
bMove[k1] = mMove[k1];
for (k4 = 2; k4 <= 9; k4++)
{
aEnd = n1; n1 = -1;
for (k3 = 0; k3 <= aEnd; k3++)
aMove[k3] = bMove[k3];
bStart = mStart[k4]; bEnd = mEnd[k4];
for (k3 = 0; k3 <= aEnd; k3++)
{
x1 = aMove[k3];
for (k2 = 0; k2 <= 8; k2++)
aCol[k2] = "";
n2 = -1;
for (k2 = 2; k2 <= k4; k2++)
{
for (k1 = 0; k1 <= 8; k1++)
{
n2++;
aCol[k1] = aCol[k1] + x1.substr(n2,1);
}
}
for (k2 = bStart; k2 <= bEnd; k2++)
{
x2 = mMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
x3 = x2.substr(k1,1);
n2 = aCol[k1].find(x3,0);
if (n2 != -1) goto aSkip;
}
n1++;
bMove[n1] = x1 + x2;
aSkip: k1 = 0;
}
}
}
ofstream appFile("Sudo4S.txt",ios::app);
appFile << "Puzzle " << pNum + 1 << endl;
appFile << mSu[pNum] << endl;
char c1[81];
x1 = "*********************************************************************************";
aEnd = n1;
for (k3 = 0; k3 <= aEnd; k3++)
{
bMove[k3].copy(c1,81);
x2 = x1; n1 = -1;
for (k2 = 3; k2 <= 11; k2++)
{
x3 = mNum[k2];
for (k1 = 0; k1 <= 8; k1++)
{
n1++;
n2 = int(c1[n1]) - 46;
x2.replace(n2,1,x3);
}
}
appFile << x2 << endl;
}
appFile << endl;
appFile.close();
}
***** 7
Create 1000 years' calendars(1776-2775)
The calendar we use today was adopted throughout all the 13 colonies in about 1775.
Of the 1000 years' calendars, and federal holiday lists, there are only 14 unique ones.
For example, 2024 calendar is the exac duplicate of 1776 calendar. There are more than
100 duplicates of each calendars of the the year types. For example, there are 108
calendars of 2025. There 2 groups of years and holiday lists. Group One: 365-day years(0-6);
Group 2: 366-day years{7-13). Each group has 7 types' years (Those years that start on Sun, Mon..Sat.)
Step 1: use 31 (0-31) consecutive ASCII characters to represent a calendar. It functions
as a mold
123456789:;<=>?@ABCDEFGHIJKLMNO...(LMNO: 28,29,30,31. 1's value is 49; 2's value is 50)
Step 2: Create a formatted holiday mold as below.
New Year: A00 Jan 1 King: Mon Jan A01Presiden: Mon Feb A02Dayligh1: Sun Mar A03
Memorial: Mon May A04Junteen: A05 Jun 19Independ: A06 Jul 4 Labor: Mon Sep A07
Columbus: Mon Oct A08Dayligh2: Sun Nov A09Veterans: A10 Nov 11Thanksgi: Thu Nov A11
Christma: A12 Dec 25 (one string variable)
A00-A12 are the data locations. We pour data into the locations.
Step 3: Line up holiday data(13 * 14: 13 holidays and 14 types' years)
SunMonTueWedThuFriSatSunMonTueWedThuFriSat
16 15 21 20 19 18 17 16 15 21 20 19 18 17
20 19 18 17 16 15 21 20 19 18 17 16 15 21
12 11 10 09 08 14 13 11 10 9 8 14 13 12
29 28 27 26 25 31 30 28 27 26 25 31 30 29
MonTueWedThuFriSatSunTueWedThuFriSatSunMon
TueWedThuFriSatSunMonWedThuFriSatSunMonTue
4 3 2 1 7 6 5 3 2 1 7 6 5 4
9 8 14 13 12 11 10 8 14 13 12 11 10 9
5 4 3 2 1 7 6 4 3 2 1 7 6 5
SatSunMonTueWedThuFriSunMonTueWedThuFriSat
23 22 28 27 26 25 24 22 28 27 26 25 24 23
MonTueWedThuFriSatSunTueWedThuFriSatSunMon
The first column: Sun,16,20,12,29,Mon,Tue,4,9,5,Sat,23,Mon are for year type 0;
They are: New Year,King,President,Day light 1,Memorial,Juneteen,Independence,
labor,Columbus,Day light 2,Veteran,Thanks,Christomas. Year 2023 belongs to the column.
The first row: New years week days for year-type of 14;
0 (1-12 are omitted)
CALENDAR
January February March April
SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA.
1 2 3 4 5 6 7 1 2 3 4 1 2 3 4 1
8 9 10 11 12 13 14 5 6 7 8 9 10 11 5 6 7 8 9 10 11 2 3 4 5 6 7 8
15 16 17 18 19 20 21 12 13 14 15 16 17 18 12 13 14 15 16 17 18 9 10 11 12 13 14 15
22 23 24 25 26 27 28 19 20 21 22 23 24 25 19 20 21 22 23 24 25 16 17 18 19 20 21 22
29 30 31 26 27 28 26 27 28 29 30 31 23 24 25 26 27 28 29
30
May June July August
SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA.
1 2 3 4 5 6 1 2 3 1 1 2 3 4 5
7 8 9 10 11 12 13 4 5 6 7 8 9 10 2 3 4 5 6 7 8 6 7 8 9 10 11 12
14 15 16 17 18 19 20 11 12 13 14 15 16 17 9 10 11 12 13 14 15 13 14 15 16 17 18 19
21 22 23 24 25 26 27 18 19 20 21 22 23 24 16 17 18 19 20 21 22 20 21 22 23 24 25 26
28 29 30 31 25 26 27 28 29 30 23 24 25 26 27 28 29 27 28 29 30 31
30 31
September October November December
SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA.
1 2 1 2 3 4 5 6 7 1 2 3 4 1 2
3 4 5 6 7 8 9 8 9 10 11 12 13 14 5 6 7 8 9 10 11 3 4 5 6 7 8 9
10 11 12 13 14 15 16 15 16 17 18 19 20 21 12 13 14 15 16 17 18 10 11 12 13 14 15 16
17 18 19 20 21 22 23 22 23 24 25 26 27 28 19 20 21 22 23 24 25 17 18 19 20 21 22 23
24 25 26 27 28 29 30 29 30 31 26 27 28 29 30 24 25 26 27 28 29 30
............................................................................................
0-13
Holiday (2022 - 2775)
New Year: Sun Jan 1
King: Mon Jan 16
Presiden: Mon Feb 20
Dayligh1: Sun Mar 12
Memorial: Mon May 29
Junteen: Mon Jun 19
Independ: Tue Jul 4
Labor: Mon Sep 4
Columbus: Mon Oct 9
Dayligh2: Sun Nov 5
Veterans: Sat Nov 11
Thanksgi: Thu Nov 23
Christma: Mon Dec 25
2022 is the year that created the last federal holiday: Juneteen(June 19)
How to pick up the calendar you want?
What is the week day of the first day of the year (n1)?
If is Sun then n1 = 0; If it is Sat then n1 = 0;
If the last day of February is 29 then n1 = n1 + 7;
e.g. for 2026 n1 = 3 (n1 + 0); 2024, n1 = 8 (1+7)
.....................
31
void aMain();
void SetUp1();
string GetYear2(int);
void hList3();
int mYtype[2776]; //Index of types of years
string mNum[32],nNum[32],mYear[14]; // Types of Years; //nNum[n] are for formatting only
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
SetUp1();
hList3();
}
void SetUp1()
{
int k1,k2, k3,n1,n2, aLead[2776];
int Month1[] = {31,28,31,30,31,30,31,31,30,31,30,31};
string x1,x2,aMonth[12],bMonth[168],aZero = "00000000000000";
for (k1 = 1; k1 <= 31; k1++)
{
x1 = char(k1+ 48);
mNum[k1] = x1;
x2 = x2 + x1; // The month has 31 days
}
mNum[0] = "0";
n1 = -1;
for (k2 = 0; k2 <= 3; k2++) //Formatted numbers. Each day is length 2;
{
x1 = mNum[k2];
if (k2 == 0) x1 = " ";
for (k1 = 0; k1 <= 9; k1++)
{
n1++;
nNum[n1] = x1 + mNum[k1];
if (n1 == 31) break;
}
}
nNum[0] = " ";
for (k1 = 0; k1 <= 11; k1++)
{
n1 = Month1[k1]; // Jan has 31, Feb has 28 or 29...
aMonth[k1] = x2.substr(0,n1);
}
n2 = -1;
for (k3 = 1; k3 <= 2; k3++) // A month can be lead by 0-6 spaces
{
for (k2 = 0; k2 <= 6; k2++)
{
n1 = k2;
for (k1 = 0; k1 <= 11; k1++)
{
x1 = aZero.substr(0,n1) + aMonth[k1];
n1 = x1.length() % 7;
n2++; bMonth[n2] = x1;
}
}
aMonth[1] = aMonth[1] + "M"; // M is 29. 0-6 are for year-365
} // 7-13 are for year-366
for (k1 = 0; k1 <= 167; k1++)
{
x1 = bMonth[k1] + aZero; // Use zeros to represent space.
bMonth[k1] = x1.substr(0,42);
}
n1 = -1;
for (k2 = 0; k2 <= 13; k2++)
{
x1 = "";
for (k1 = 1; k1 <= 12; k1++)
{
n1++;
x1 = x1 + bMonth[n1];
}
mYear[k2] = x1; // One line for one year. Coded calendars // A year has 504 days
} // incl. space.
for (k1 = 1776; k1 <= 2775; k1++) // 1000 years are organized into 2 groups:
{ //year 365 and year 366. And then they are
if (k1 % 4 != 0) // subdivided to 7 per group according to
aLead[k1] = 1; // the week day of the first day of the year
else // sun - sat
{
aLead[k1] = 2;
if (k1 % 100 == 0 && k1 % 400 != 0)
aLead[k1] = 1;
}
}
n1 = 1;
for (k1 = 1776; k1 <= 2775; k1++)
{
mYtype[k1] = n1;
n1 = (n1 + aLead[k1]) % 7;
}
for (k1 = 1776; k1 <= 2775; k1++)
if (aLead[k1] == 2) mYtype[k1] = mYtype[k1] + 7; //common years: 0-6. Lead: 7-13
ofstream OutFile("ForeverCal.txt",ios::out);
for (k2 = 0; k2 <= 13; k2++)
{
OutFile << k2 << endl;
x1 = GetYear2(k2);
n1 = -96;
for (k1 = 0; k1 <= 27; k1++) // A calendar has 28 lines with length in 96
{
n1 = n1 + 96;
OutFile << x1.substr(n1,96) << endl;
}
OutFile << endl;
}
OutFile.close();
}
string GetYear2(int pNum) // Decode all the data for the calendar and format them.
{
int k1,k2, k3,n1,n2;
string x1,aMonth[12],bMonth[18],aBlank,aYear,Title1[13];
char c1[32];
x1 = mYear[pNum];
n1 = -42;
for (k1 = 0; k1 <= 11; k1++) // Standardize the month to 6 weeks and length of 42
{
n1 = n1 + 42;
aMonth[k1] = x1.substr(n1,42);
}
n2 = -1;
for (k3 = 0; k3 <= 8; k3+= 4) // lines: 17; length 32. Line up 4 months per row.
{ // 3 sections
n1 = -7;
for (k2 = 0; k2 <= 5; k2++)
{
x1 = ""; n1 = n1 + 7;
for (k1 = k3; k1 <= k3 + 3; k1++)
{
x1 = x1 + aMonth[k1].substr(n1,7) + "0";
}
n2++;
bMonth[n2] = x1;
}
}
for (k1 = 0; k1 <= 95; k1++) // Calendar is 28 lines and 96 in length per line
aBlank = aBlank + " ";
aYear = aBlank.substr(0,44) + "CALENDAR" + aBlank.substr(0,44);
Title1[0] = " January February March April ";
Title1[6] = " May June July August ";
Title1[12] = " September October November December ";
string Title2 = "SU MO TU WE TH FR SA SU MO TU WE TH FR SA ";
Title2 = Title2 + "SU MO TU WE TH FR SA SU MO TU WE TH FR SA. ";
for (k3 = 0; k3 <= 12; k3+= 6)
{
aYear = aYear + Title1[k3] + Title2;
for (k2 = k3; k2 <= k3 + 5; k2++)
{
bMonth[k2].copy(c1,32); x1 = "";
for (k1 = 0; k1 <= 31; k1++)
{
n1 = int(c1[k1]) - 48;
x1 = x1 + nNum[n1] + " ";
}
aYear = aYear + x1;
}
aYear = aYear + aBlank;
}
return aYear;
}
void hList3() // Creat 14 federal holidays per year.
{
int k1,k2, n1,n2,aPosit[13];
string x1,x2,aMode,bMode[14],aDay[182], aTarget;;
ifstream InFile("Holid.txt",ios::in);
for (k1 = 0; k1 <= 12; k1++)
{
getline(InFile,x1); x2 = x2 + x1.substr(0,42);
}
getline(InFile,aTarget);
getline(InFile,aMode);
InFile.close();
n1 = -3;
for (k1 = 0; k1 <= 181; k1++) // 13 holidays per years * 14 types of years = 182
{
n1 = n1 + 3;
aDay[k1] = x2.substr(n1,3);
}
for (k1 = 0; k1 <= 13; k1++) // 14 types' of years means 14 holiday modes
bMode[k1] = aMode; //The same 14 modes with different data in them
n1 = -3; n2 = 0;
for (k1 = 0; k1 <= 12; k1++) // aTargets: A00-A12, are to be replaced with data
{
n1 = n1 + 3;
x1 = aTarget.substr(n1,3); // day and week are standardizes to length 3;
n2 = aMode.find(x1,n2);
aPosit[k1] = n2; n2++; // Posit means the positions of the mode to be replaced
}
n2 = -1;
for (k2 = 0; k2 <= 12; k2++)
{
n1 = aPosit[k2];
for (k1 = 0; k1 <= 13; k1++)
{
n2++;
bMode[k1].replace(n1,3,aDay[n2]);
}
}
ofstream OutFile("ForeverHoli.txt",ios::out); // 2022- 2775 have only 14 unique holiday
for (k2 = 0; k2 <= 13; k2++) // lists.
{
OutFile << k2 << endl;
x1 = bMode[k2];
n1 = -21; //The length of each item of holiday list is 21
for (k1 = 0; k1 <= 12; k1++)
{
n1 = n1 + 21;
OutFile << x1.substr(n1,21) << endl;
}
OutFile << endl;
}
OutFile.close();
}
***** 8
The Hanoi Towers Problem
A simple explanation:
There is a 3-deck of cards, ordered and valued 1-3
in Box 1. There are also Box 2 and 3. Both are empy. The task is A:
move, one by one, all cards from Box 1 to Box 2. You are allowed
to move cards among the 3 boxes. But you are not allowed to put
a card valued greater on top of the card valued lesser; B: Complete
the relocation using fewer moves as possible.
Try-out by hand:
Through this try we can see A: The first move: it goes to Box 2
if the card count is odd numbered. If the count is even numbered,
it goes to Box 3. B: The fewest required moves. We list the moves
by the number of cards
N: number of cards; M: the required moves;
N M
1 1 2 Power 1 - 1
2 3 2 Power 2 - 1
3 7 2 Power 3 - 1
We equationize: M = 2 power N - 1
We can further realize that there are only 3 types of card movement.
1. Movement between Box 1 and Box 2;
2. Movement between Box 1 and Box 3;
3. Movement between Box 2 and Box 3;
We use 12,13 and 23 as well as ABC to represent the 3 movemets.
For 2 cards, all movement is: BAC
For 3 cards, all movement is: ABCABCA
How do we avoid putting a bigger card on a smaller card or trying
to pick a card from an empty box?
We reverse the move direction. e.g. 12 become 21, 13 become 31,
23 become 32.
It is time to move the cards.
We use one array, Box[10], to represent all 3 boxes for card count of 3.
(0-2: Box 1; 3-5: Box 2; 6-9: Box 3). We load 3 cards into Box 1 by setting
the values of Box[0-2] as 1,2,3. Initialize Box[3-9] as 0;
The actual moves:
1 2 3 4 5 6 7
12 13 23 12 13(31) 23(32) 12
1 - - - - - - - - - - - - - - - - - - - - - 1 -
2 - - 2 - - - - - - - 1 - - 1 - - - - 2 - - 2 -
3 - - 3 1 - 3 1 2 3 - 2 - 3 2 1 3 2 1 3 - - 3 -
void Move1()//Make a list of stack to stack moves for a tower with 10 disks
{ //The moves for towers of 2 to 9 are subset of the moves for tower of 10.
int k1,k2,n1 = -1,n2 = 0,aStep,aDisk,bDisk,aRever[33],aSwich[33];
int aStack[30],aStart, bStart, aPosit, bPosit, aMove[1023];
int Stack1[24], Stack2[24];
string x1,x2, bMove[11];
for (k1 = 0; k1 <= 9; k1++)//Use an array of 0-29 to represent 3 stacks
aStack[k1] = k1; // Stack 1(0-9),stack 2 (10-19), stack 3 (20-29)
for (k1 = 10; k1 <= 29; k1++)//Smallest disk values 0. biggest: 9
aStack[k1] = 10; //no disk position valued 10
aMove[0] = 13; aMove[1]= 12; aMove[2] = 23;// 13 = Stack 1 to 3 etc.
for (k1 = 0; k1 <= 1022; k1++)//10 disks need 1023 moves(repetition of 13,12,23).
{
n1 = (n1 + 1) % 3;
aMove[k1] = aMove[n1];
}
aRever[12] = 21; aRever[13] = 31; aRever[23] = 32;
aSwich[12] = 13; aSwich[13] = 12; aSwich[21] = 31;//Towers with odd numbers use 13,12
aSwich[31] = 21; aSwich[23] = 32; aSwich[32] = 23;//23 while even numbers use 12,13,23
Stack1[12] = 0; Stack1[13] = 0; Stack1[23] = 10; //12 means position 0 (stack 1)
Stack2[12] = 10; Stack2[13] = 20; Stack2[23] = 20;//12 means position 10 (stack 2)
for (k2 = 0; k2 <= 1022; k2++) // Order 12: looping through stack 1 and 2 and get the
{ // 2 positions and 2 values to decide stack 1 to 2
aStep = aMove[k2]; // or reverse the 12 to 21
aStart = Stack1[aStep]; bStart = Stack2[aStep];
aPosit = aStart + 9; aDisk = 10; // 10 here means 0, empty
for (k1 = aStart; k1 <= aStart + 9; k1++)
{
if (aStack[k1] != 10)// If the stack is not empty
{
aPosit = k1; aDisk = aStack[k1];
break;// aPosit: the element of the array
} // aDisk: the value of the disk
}
bPosit = bStart + 9; bDisk = 10;
for (k1 = bStart; k1 <= bStart + 9; k1++)
{
if (aStack[k1] != 10)
{
bPosit = k1; bDisk = aStack[k1];
break;
}
}
if (aDisk < bDisk)//If aDisk is smaller than bDisk or bStack is empty
{
if (bDisk == 10)
aStack[bPosit] = aDisk;
else
aStack[bPosit-1] = aDisk;
aStack[aPosit] = 10;
}
else //Reverse the move
{
if (aDisk == 10)
aStack[aPosit] = bDisk;
else
aStack[aPosit-1] = bDisk;
aStack[bPosit] = 10;
aStep = aRever[aStep];
}
x1 = x1 + mNum[aStep]; // x1 are the moves for even numbered towers
if (k2 < 511) // x2 are the moves for odd numbered towers
{
n1 = aSwich[aStep]; x2 = x2 + mNum[n1];
}
}
for (k1 = 2; k1 <= 10; k1+= 2) // Store the moves into an array of bMove[n]
{
n1 = pow(2,k1) -1; // List the moves by the disk count. One line per count
bMove[k1] = x1.substr(0,n1);
}
for (k1 = 3; k1 <= 9; k1+= 2)
{
n1 = pow(2,k1) -1;
bMove[k1] = x2.substr(0,n1);
}//Tower1.txt: coded representation for stack to stack moves
//ASCII consecutively characters <=EGOP for 12,13,21,23,31,32
ofstream OutFile("Tower1.txt", ios::out); // Tower with 2 disks has 3 moves(=> x1; aLen = x1.length() - 1;
x1.copy(c1,aLen + 1); x2 = "";
bLen = k3 * 3 - 1;
for (k2 = 0; k2 < k3; k2++)
aStack[k2] = k2;
for (k2 = k3; k2 <= bLen; k2++)
aStack[k2] = 10;
for (k2 = 0; k2 <= bLen; k2++)
{
n1 = aStack[k2];
x2 = x2 + mNum[n1];
}
for (k2 = 0; k2 <= aLen; k2++)
{
n1 = int(c1[k2]) - 48;
aStart = (n1 / 10 - 1) * k3; aEnd = aStart + k3 -1;
bStart = (n1 % 10 - 1) * k3; bEnd = bStart + k3 -1;
aPosit = aEnd;
for (k1 = aStart; k1 <= aEnd; k1++)
if (aStack[k1] != 10)
{
aPosit = k1; break;
}
bPosit = bEnd;
for (k1 = bStart; k1 <= bEnd; k1++)
if (aStack[k1] != 10) // Normal disk moves: 12.13.23
{
bPosit = k1; break;
}
if (aStack[bPosit] != 10) bPosit = bPosit -1; //Reverse moves 21,31,32
aStack[bPosit] = aStack[aPosit]; aStack[aPosit] = 10;
x1= "";
for (k1 = 0; k1 <= bLen; k1++)
{
n1 = aStack[k1];
x2 = x2 + mNum[n1];
}
}
aMove[k3] = x2; // Solve all puzzles (disk 2 to 10) and string them up
} // in 9 lines of data. They still need to be decoded and formatted.
InFile.close();
ofstream OutFile("Tower2.txt", ios::out);//Decoded solution one line for
for (k1 = 2; k1 <= 10; k1++) //one disk count (2-10)
OutFile << aMove[k1] << endl;
OutFile.close();
}
void Move3() // Decode all solution into linear form
{
int k1,k2,k3, k4,n1,n2;
int L2, L3, aStep;
string x1,x2,aTower,bTower;
ifstream InFile("Tower2.txt", ios::in);
ofstream OutFile("Tower3.txt", ios::out);//Tower3.txt: 1-D
for (k4 = 2; k4 <= 10; k4++) //solutions for Hanoi Towers
{
InFile >> aTower;
bTower = "";
L2 = k4 - 1; // 2 disks = 0,1 lines
L3 = pow(2,k4) - 1; // and 3 disk moves
aStep = k4 * 3; // a move of 2-disk is 6 characters in length, 3 is 9 characters.
n1 = 0;
for (k3 = 0; k3 <= L3; k3++)
{
x1 = aTower.substr(n1,aStep); n1 = n1 + aStep; // Display line by line
for (k2 = 0; k2 <= L2; k2++)
{
n2 = k2;
for (k1 = 0; k1 <= 2; k1++)
{
bTower = bTower + x1.substr(n2,1) + " ";
n2 = n2 + k4; // // Space off moves
}
}
}
OutFile << bTower << endl;;
}
OutFile.close();
InFile.close();
}
// Set font to Courier New
void Print4()// Change all solutions from one-dimension to 2-dimension and formatted.
{ // with proper title and subtitles.
int k1,k2,k3,n1,n2,aCount = -1, bCount,aLen,bStack,aEnd;
string x1,x2,aStack[11],cStack[1024],aMove[11], bMove,cMove[22520];
char c1[1024];
ifstream aInFile("Tower1.txt", ios::in);
for (k1 = 2; k1 <= 10; k1++)
aInFile >> aStack[k1];
aInFile.close();
ifstream bInFile("Tower3.txt", ios::in);
for (k1 = 2; k1 <= 10; k1++)
getline(bInFile,aMove[k1]);
bInFile.close();
mNum[10] = "10";
for (k3 = 2; k3 <= 10; k3++)
{
bMove = aMove[k3]; bCount = -1;
aEnd = pow(2,k3); n1 = aEnd -1; aLen = aEnd -2;
ostringstream convert; convert << n1; x1 = convert.str();
aStack[k3].copy(c1,n1); // First copy a string into a char array
for (k2 = 0; k2 <= aLen; k2++)
{
bStack = int(c1[k2]) - 48; // then change char into integer
n1 = bStack / 10; n2 = bStack % 10; // Get the stack codes (12,13,23)
cStack[k2] = " " + mNum[n1] + "-" + mNum[n2]; // Format 12 to 1-2 etc.
}
aCount = aCount + 1;
cMove[aCount] = " " + mNum[k3] + " disks and " + x1 + " moves"; // Subtitles
n1 = 0;
for (k2 = 1; k2 <= aEnd; k2++)
{
for (k1 = 1; k1 <= k3; k1++)
{
aCount = aCount + 1;
cMove[aCount] = " " + bMove.substr(n1,6); n1 = n1 + 6;
} // Each line is 6 in length // 0 - - - - - - - - - - -
if (k2 != aEnd) // 1 - - 1 - - - - - - - 0
{ // 2 - - 2 0 - 2 0 1 2 - 1
aCount = aCount + 1;
cMove[aCount] = "";
}
aCount++; bCount++; // aCount is total lines
cMove[aCount] = cStack[bCount]; // bCount is data lines
}
}
//Tower4.txt: Formatted, 2-D solutions of Hanoi Towers
ofstream OutFile("Tower4.txt", ios::out);
OutFile << "Hanoi Towers (2-10 disks. 10 Disks = 1023 moves)" << endl;
OutFile << "1-2 (means pick up a disk from Stack 1 and drop it down Stack 2)." << endl;
for (k1 = 0; k1 <= aCount; k1++)
OutFile << cMove[k1] << endl;
OutFile.close();
}
***** 9
Coding TicTaToe Game (A user against the program)
The program has 5 short subprograms
Part 1: The program as the first mover against a user
It compiles a list of all possible moves by the user and the program's couter moves.
Part 2: The user as the first mover against the program
It compiles a list of all possible moves by the user and the program's couter moves.
Part 3: The program as the first mover against a user
It compiles a list of all full games both in coded form and in uncoded form
Part 4: The user as the first mover against the program
It compiles a list of all full games both in coded form and in uncoded form
Part 5. User plays Tictatoe by typing numbers (1-9, the gameboard has 9 cells for
9 moves. The program displays on screen 2-D gameboard showing the game's
progress as follows:
- - - - - - 2 - - 2 - 1 2 - 1 2 - 1
- - - - 1 - - 1 - - 1 - 2 1 - 2 1 -
- - - - - - - - - - - - - - - 1 - - Checkmate!
Overview
Using a "snapshot" to represent every move of the game
The gameboard has 9 cells and their IDs are 012345678. I use "000000000" to
represent the empty gameboard, 1 represents moves by player 1 and 2 by player 2.
When player 1 (P1) puts one of his pieces on cell 4, I imaginably took a photo shot
on the board, and the snapshot is "000010000". P2 moves to cell 0 and the snapshot is
"200010000". The whole game is represented by "000010000,200010000,200010100,200210100,
201210100" checkmate
012 - - - - - - 2 - - 2 - - 2 - - 2 - 1
345 - - - - 1 - - 1 - - 1 - 2 1 - 2 1 -
678 - - - - - - - - - 1 - - 1 - - 1 - - checkmate
I start with an empty board: Game = "000000000";
P1 moves on cell 4. I code: Game.replace(4,1,"1"); Game = "000010000";
P2 moves on cell 0. I code: Game.replace(0,1,"2"); Game = "200010000";
I also use move-by-move representation, just to make it more error-proof
I use 40236 to represent the above game. 40236 is read: P1 moves on cell 4,
P2 moves on cell 0, P1 moves on cell 2, etc.
The two representations are easily convertable.
The strategy is:
I first permutate all possible moves and code them into snapshots, and save them
into a text file list.I actually turn the game into some kind of Q & A.
The user asks a question by making a move. The program answers the question with
a couter moves.
The list is formeted as below:
000010000 200010000 c
201010000 201210000 c
When P1 moves to cell 4, the snapshot is "000010000", we pass the shot down the list
We find a match and break. We get 200010000.
Next, I permutate all all possible games (total: 597) and use all these games to check
on the snapshot game playing.
The program decides couter moves against the user by following the priority list:
1. Is there a check-lineup for me, so that I must checkmate him?
2. Is there a check-lineup against me, so that I must prevent a checkmate?
3. Is there a move I make to get a double-check-lineup for a sure checkmate?
4. Is there a move I make for a check-lineup. The move will not provide the
user a chance for a double-check-lineup against me?
e.g. I am a player 2 and game board is:
012 2 - - 2 2 - 2 2 1
345 - 1 - - 1 - - 1 -
678 - - 1 - - 1 - - 1
In this situation, if I move to cell 1 and form a check-lineup, player 2
will move to cell 2 and forms a double-check-lineup
5. Is there a move I make to form a check-lineup and by blocking my lineup
he will form a lineup against me (so I can block him and create more favourite
situation for me.
6. Fill in any empty cell.
The gameboard has only 9 cells. For simpler and more efficient processing, I index the
9 cells into a straight line, 24 cells and 8 3-cell units. So instead of 012345678
I have 012 345 678 036 147 258 048 246. When I load up an in-progress game, I know what
is going on in this situation
2 1 0
2 0 1
0 1 0
I Filter out 0, an I get 21, 21, 1,22, 11,1, 2,"". I see there is a check-lineup for both
player 1 and 2. Since it is the player 2' move, he moves to cell 6 and checkmate.
If I see 111 or 222 then the game is over.
Here is the program
Par 1
void aMain();
void Move1();
void Move2();
void Move3();
int Move3a(string);
void LineUp4();
int Move4a(string);
//mCheck[n] is used to re-organized the 9 cells of board by row,column
// and diagonal to a linear 24 cells to simplify and speed up processing
// This technique applies to chess(2-D) and Sudoku(3-D).Just indexing
int mStart, mEnd; // up their cells. It's effect looks like miracle
int mCheck[] = {0,1,2,3,4,5,6,7,8,0,3,6,1,4,7,2,5,8,0,4,8,2,4,6};
string mNum[] = {"0","1","2","3","4","5","6","7","8"};
string mMove[150],nMove[150]; //mMove for Player 1 and nMove for Player 2
string mShow[] = {"-","-","-","-","-","-","-","-","-"};
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
Move1();
Move2();
Move3();
LineUp4();
}
void Move1() // Move 4th; array 8-45
{
int k1,k2,n1, aCount = -1, aLen;
string x1,x2, aMove[48];
string y1[] =
{"200010000","020010000","002010000","000210000","000012000","000010200","000010020","000010002"};
string y2[] =
{"200010001","120010000","002010100","100210000","100012000","001010200","100010020","100010002"};
// 1-D 200010000 can be read in 2-D form.
// 200
// 010
// 000
// All player 1's moves start on cell 4 (the center)
for (k1 = 0; k1 <= 7; k1++)
{
nMove[k1] = y1[k1]; // Moves by Player 2
mMove[k1] = y2[k1]; // Moves by Player 1
}
for (k2 = 0; k2 <= 7; k2++) // Permutate all possible the 4th moves
{ // by a user.
x1 = mMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
x2 = x1.substr(k1,1);
if (x2 == "0")
{
aCount++;
aMove[aCount] = x1;
aMove[aCount].replace(k1,1,"2");
}
} //47
}
aLen = aCount; aCount = 7;
for (k2 = 0; k2 <= aLen; k2++)
{
x1 = aMove[k2];
for (k1 = k2 + 1; k1 <= aLen; k1++)
if (x1 == aMove[k1]) goto aSkip; // Filter out duplicates
aCount++;
nMove[aCount] = x1; // Now the game prograsses to the 4th moves
aSkip: k1 = 0;
}
mStart = 8; mEnd = aCount; //45
}
void Move2() // Move 5th; array 8-45; Counter moves
{ // (the 5th moves by program)
int k1,k2, k3,k4,n1,n2, aPosit[46], bPosit;
string x1,x2,aIndex[9];
for (k3 = mStart; k3 <= mEnd; k3++)
{
x1 = nMove[k3]; aPosit[k3] = -1;
for (k2 = 0; k2 <= 8; k2++)
{
x2 = x1.substr(k2,1);
if (x2 == "0") x2 = "";
aIndex[k2] = x2; // Load the game into a 9-cell array
}
// mCheck[0-23] displays all 8 units one by one
// and row by row, column by colum and diagonal by diagonal
bPosit = -1;
for (k2 = 0; k2 <= 21; k2+= 3)
{
x2 = "";
for (k1 = k2; k1 <= k2 + 2; k1++)
{
n1 = mCheck[k1];
if (aIndex[n1] == "") n2 = n1;
x2 = x2 + aIndex[n1];
}
if (x2 == "11") // If a unit has 2 of my pieces
{ // and an empty cell. That cell is my choice
aPosit[k3] = n2; goto aSkip;
}
if (x2 == "22") bPosit = n2; // If a unit has 2 of enemy's,
} // this is my second choice
if (bPosit != -1) aPosit[k3] = bPosit;
aSkip: k1 = 0;
}
// Having taking care of all games with checkmate possiblity of both me and
for (k4 = mStart; k4 <= mEnd; k4++) // my apponent, we look for a move
{ // that is a winning sure double-check: by row,
if (aPosit[k4] == -1) // column and diagonal
{ // 1 2 - 1 2 -
x1 = nMove[k4]; // - 1 - - 1 -
for (k3 = 0; k3 <= 8; k3++) // - - 2 1 - 2
{
x2 = x1.substr(k3,1);
if (x2 == "0") x2 = "";
aIndex[k3] = x2;
}
for (k3 = 0; k3 <= 8; k3++)
{
if (aIndex[k3] == "")
{ //Put 1 on every empty cell
aIndex[k3] = "1"; n2 = 0;
for (k2 = 0; k2 <= 21; k2+= 3)
{
x2 = "";
for (k1 = k2; k1 <= k2 + 2; k1++)
{
n1 = mCheck[k1];
x2 = x2 + aIndex[n1];
} // Count all units to see if there are
if (x2 == "11") n2 = n2 + 1; //2 units
} //that have 2 "11"
if (n2 == 2)
{
aPosit[k4] = k3; goto bSkip;
}
aIndex[k3] = ""; // If you don't get a double-check,
} // put back the 0
}
bSkip: k1 = 0;
}
}
for (k1 = mStart; k1 <= mEnd; k1++)
{
n1 = aPosit[k1]; mMove[k1] = nMove[k1];
mMove[k1].replace(n1,1,"1");//Player 1 actually makes the moves here.
}
}
void Move3()
{
int k1,k2, k3,n1,n2, aCount = -1,aLen, aPosit[134], bPosit;
string x1,x2,aMove[134], bMove[96],aIndex[9];
for (k1 = mStart; k1 <= mEnd; k1++)
{
n1 = Move4a(mMove[k1]); //Filter out the moves that have "111"
if (n1 == -1)
{
aCount++;
aMove[aCount] = mMove[k1];
} // 23
}
aLen = aCount; aCount = -1;
for (k2 = 0; k2 <= aLen; k2++) // Permutate moves by a user
{
x1 = aMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
x2 = x1.substr(k1,1);
if (x2 == "0")
{
aCount++;
bMove[aCount] = x1;
bMove[aCount].replace(k1,1,"2"); //2 means player 2
} //the user
}
}
mStart = mEnd + 1; aLen = aCount;
aCount = mEnd;
for (k2 = 0; k2 <= aLen;k2++) //Filter out the duplicates
{
x1 = bMove[k2];
for (k1 = k2 + 1; k1<= aLen; k1++)
if (x1 == bMove[k1]) goto aSkip;
aCount++;
nMove[aCount] = x1;
aSkip: k1 = 0;
} //Moves 6th; array: 46-133
mEnd = aCount;
for (k3 = mStart; k3 <= mEnd; k3++)
{
x1 = nMove[k3]; aPosit[k3] = -1;
for (k2 = 0; k2 <= 8; k2++)
{
x2 = x1.substr(k2,1);
if (x2 == "0") x2 = "";
aIndex[k2] = x2;
}
bPosit = -1;
for (k2 = 0; k2 <= 21; k2+= 3)
{
x2 = "";
for (k1 = k2; k1 <= k2 + 2; k1++)
{
n1 = mCheck[k1];
if (aIndex[n1] == "") n2 = n1;
x2 = x2 + aIndex[n1];
}
if (x2 == "11")
{
aPosit[k3] = n2; goto bSkip;
}
if (x2 == "22") bPosit = n2;
}
if (bPosit != -1) aPosit[k3] = bPosit;
bSkip: k1 = 0;
}
for (k1 = mStart; k1 <= mEnd; k1++)
{
n1 = aPosit[k1];
if (n1 == -1) aPosit[k1] = Move3a(nMove[k1]);
}
for (k1 = mStart; k1 <= mEnd; k1++)
{
n1 = aPosit[k1];
mMove[k1] = nMove[k1]; //Continue the game by replacing 0 with 1
mMove[k1].replace(n1,1,"1");
} //Moves: 7th
aCount = mEnd; aCount = -1;
for (k1 = mStart; k1 <= mEnd; k1++) // filter out game-over moves
{
x1 = mMove[k1];
n1 = Move4a(x1);
if (n1 == -1)
{
aCount ++;
aMove[aCount] = x1;
}
}
aLen = aCount; mStart = mEnd + 1; aCount = mEnd;
for (k2 = 0; k2 <= aLen; k2++)
{
x1 = aMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
x2 = x1.substr(k1,1);
if (x2 == "0")
{
aCount++;
nMove[aCount] = x1;
nMove[aCount].replace(k1,1,"2");
}
}
} // moves 8th;
mEnd = aCount;
for (k1 = mStart; k1 <= mEnd; k1++)
{
x1 = nMove[k1];
n1 = x1.find("0",0);
mMove[k1] = x1.replace(n1,1,"1");
} // Moves 9th; array: 134-149
}
int Move3a(string pMove)
{
int k1,k2, k3,n1,n2, aCell;
string x1,aIndex[9];
for (k3 = 0; k3 <= 8; k3++)
{
x1 = pMove.substr(k3,1);
if (x1 == "0") x1 = "";
aIndex[k3] = x1;
}
for (k3 = 0; k3 <= 8; k3++)
{
if (aIndex[k3] == "")
{
aIndex[k3] = "1";
for (k2 = 0; k2 <= 21; k2+= 3)
{
x1 = "";
for (k1 = k2; k1 <= k2 + 2; k1++)
{
n1 = mCheck[k1];
x1 = x1 + aIndex[n1];
}
if (x1 == "11")
{
aCell = k3; goto bSkip;
}
}
aIndex[k3] = "";
}
}
bSkip: k1 = 0;
return aCell;
}
void LineUp4() // The total snapshots: 0-149
{
int k1,n1;
string x1,x2,x3,aMove;
ofstream OutFile("TicA149.txt", ios::out);
for (k1 = 0; k1 <= mEnd; k1++)
{
x1 = nMove[k1]; x2 = mMove[k1];
n1 = Move4a(x2);
if (n1 == -1)
x3 = " c"; //Tied games
else
x3 = " w"; //Winning games
aMove = x1 + " " + x2 + x3;
OutFile << aMove << endl;
}
OutFile.close(); // 200010000 200010001 c The first of the list
} // 122110212 122111212 w The last of the list
// c: continue; w: game is won(over)
int Move4a(string pMove) // Find out if there is a checkmate(game's over)
{
int k1,n1,n2;
string aMove;
for (k1 = 0; k1 <= 23; k1++)
{
n1 = mCheck[k1];
aMove = aMove + pMove.substr(n1,1);
n2 = (k1 + 1) % 3;
if (n2 == 0) aMove = aMove + " ";
}
n1 = aMove.find("111", 0); // a "111" by row, or column or diagonal
return n1; // signals game's over.
}
Part 2
//User as player 1 and this program as Player 2;
void aMain();
void Move1();
void Move2();
int Move2a(string);
void Move3();
void Move4();
int Move4a(string);
void LineUp5();
int mStart, mEnd;
int mCheck[] = {0,1,2,3,4,5,6,7,8,0,3,6,1,4,7,2,5,8,0,4,8,2,4,6};
string mMove[318],nMove[318];
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
int k1,n1;
Move1();
Move2();
Move3();
Move4();
LineUp5();
}
void Move1() // array: 0-8
{
int k1,k2,n1,n2 , aCount = -1, aLen;
string x1,x2, aMove[63];
string y1[] =
{"100000000","010000000","001000000","000100000","000010000","000001000","000000100","000000010","000000001"};
string y2[] =
{"100020000","010020000","001020000","000120000","200010000","000021000","000020100","000020010","000020001"};
for (k1 = 0; k1 <= 8; k1++)
{
mMove[k1] = y1[k1]; //Move: 1th by user
nMove[k1] = y2[k1]; //Move: 2th by this program
}
for (k2 = 0; k2 <= 8; k2++)
{
x1 = nMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
x2 = x1.substr(k1,1);
if (x2 == "0")
{
aCount++;
aMove[aCount] = x1;
aMove[aCount].replace(k1,1,"1");
}
}
}
aLen = aCount; aCount = 8;
for (k2 = 0; k2 <= aLen; k2++)
{
x1 = aMove[k2];
for (k1 = k2 + 1; k1 <= aLen; k1++)
{
if (x1 == aMove[k1]) goto aSkip;
}
aCount++;
mMove[aCount] = x1;
aSkip: k1 = 0;
}
mStart = 9; mEnd = aCount;// Array: 9-43
}
void Move2() // Move 5th; array: 44-204
{
int k1,k2, k3,n1,n2,aCount = -1,aLen,aPosit[158];
string x1,x2,aIndex[9],aMove[175];
for (k3 = mStart; k3 <= mEnd; k3++)
{
x1 = mMove[k3]; aPosit[k3] = -1;
for (k2 = 0; k2 <= 8; k2++)
{
x2 = x1.substr(k2,1);
if (x2 == "0") x2 = "";
aIndex[k2] = x2;
}
for (k2 = 0; k2 <= 21; k2+= 3)
{
x2 = "";
for (k1 = k2; k1 <= k2 + 2; k1++)
{
n1 = mCheck[k1];
if (aIndex[n1] == "") n2 = n1;
x2 = x2 + aIndex[n1];
}
if (x2 == "11")
{
aPosit[k3] = n2; goto aSkip;
}
}
aPosit[k3] = Move2a(x1);
aSkip: k1 = 0;
}
for (k3 = mStart; k3 <= mEnd; k3++)
{
n1 = aPosit[k3];
nMove[k3] = mMove[k3];
nMove[k3].replace(n1,1,"2");
}
for (k3 = mStart; k3 <= mEnd; k3++)
{
x1 = nMove[k3];
for (k2 = 0; k2 <= 8; k2++)
{
x2 = x1.substr(k2,1);
if (x2 == "0") x2 = "";
aIndex[k2] = x2;
}
for (k2 = 0; k2 <= 8; k2++)
{
if (aIndex[k2] == "")
{
aCount++;
aMove[aCount] = x1;
aMove[aCount].replace(k2,1,"1");
}
}
}
aLen = aCount; aCount = mEnd;
for (k2 = 0; k2 <= aLen; k2++)
{
x1 = aMove[k2];
for (k1 = k2 + 1; k1 <= aLen; k1++)
{
if (x1 == aMove[k1]) goto bSkip;
}
aCount++;
mMove[aCount] = x1;
bSkip: k1 = 0;
}
mStart = mEnd + 1; mEnd = aCount; // Move 5th
}
int Move2a(string pMove)
{
int k1,k2, k3,n1 = -1,n2, aKey, bKey,aPosit[9];
string x1,x2,aMove[6],bMove,aIndex[9];
bool aFlag;
for (k3 = 0; k3 <= 8; k3++)
{
x1 = pMove.substr(k3,1);
if (x1 == "0" )
{
n1++;
aMove[n1] = pMove; aMove[n1].replace(k3,1,"2");
aPosit[n1] = k3;
}
}
for (k3 = 0; k3 <= 5; k3++)
{
bMove = aMove[k3];
for (k2 = 0; k2 <= 8; k2++)
{
x1 = bMove.substr(k2,1);
if (x1 == "0") x1 = "";
aIndex[k2] = x1;
}
aFlag = false;
for (k2 = 0; k2 <= 21; k2+= 3)
{
x2 = "";
for (k1 = k2; k1 <= k2 + 2; k1++)
{
n1 = mCheck[k1];
if (aIndex[n1] == "") n2 = n1;
x2 = x2 + aIndex[n1];
}
if (x2 == "22")
{
aFlag = true;
aIndex[n2] = "1";
goto aSkip;
}
}
if (aFlag == false) goto bSkip;
aSkip: k1 = 0; bKey = n2; n2 = 0;
for (k2 = 0; k2 <= 21; k2+= 3)
{
x2 = "";
for (k1 = k2; k1 <= k2 + 2; k1++)
{
n1 = mCheck[k1];
x2 = x2 + aIndex[n1];
}
if (x2 == "11") n2++;
}
aKey = -1;
if (n2 == 1)
{
aKey = aPosit[k3];
goto aBottom;
}
if (n2 != 1) aIndex[bKey] = "";
bSkip: k1 = 0;
}
aBottom: k1 = 0;
return aKey;
}
void Move3() // Move 7th; array: 317
{
int k1,k2, k3,n1,n2, n3,aCount = -1, aLen;
int aPosit[599],bPosit[] = {3,3,1,6,1,1,3};
string x1,x2,aMove[318], bMove[318],aIndex[9];
for (k3 = mStart; k3 <= mEnd; k3++)
{
x1 = mMove[k3]; aPosit[k3] = -1;
for (k2 = 0; k2 <= 8; k2++)
{
x2 = x1.substr(k2,1);
if (x2 == "0") x2 = "";
aIndex[k2] = x2;
}
n3 = -1;
for (k2 = 0; k2 <= 21; k2+= 3)
{
x2 = "";
for (k1 = k2; k1 <= k2 + 2; k1++)
{
n1 = mCheck[k1];
if (aIndex[n1] == "") n2 = n1;
x2 = x2 + aIndex[n1];
}
if (x2 == "22") // Player 2' checkmate
{
aPosit[k3] = n2; goto aSkip;
}
if (x2 == "11")
n3 = n2;
}
if (n3 != -1) aPosit[k3] = n3;
aSkip: k1 = 0;
if (aPosit[k3] == -1)
{
aCount++; cout << mMove[k3] << endl;
aPosit[k3] = bPosit[aCount]; // Move made manually
}
}
for (k3 = mStart; k3 <= mEnd; k3++)
{
n1 = aPosit[k3];
nMove[k3] = mMove[k3];
nMove[k3].replace(n1,1,"2");
}
aCount = -1;
for (k1 = mStart; k1 <= mEnd; k1++)
{
x1 = nMove[k1];
n1 = Move4a(x1);
if (n1 == -1)
{
aCount++;
aMove[aCount] = x1;
}
}
aLen = aCount; aCount = -1;
for (k2 = 0; k2 <= aLen; k2++)
{
x1 = aMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
x2 = x1.substr(k1,1);
if (x2 == "0")
{
aCount++;
bMove[aCount] = x1;
bMove[aCount].replace(k1,1,"1");
}
}
}
aLen = aCount; aCount = mEnd;
for (k2 = 0; k2 <= aLen; k2++)
{
x1 = bMove[k2];
for (k1 = k2 + 1; k1 <= aLen; k1++)
if (x1 == bMove[k1]) goto bSkip;
aCount++;
mMove[aCount] = x1;
bSkip: k1 = 0;
}
mStart = mEnd + 1; mEnd = aCount;
}
void Move4() // Move 8th: last move; 9th moves are unnecessary
{
int k1,k2, k3,n1,n2,aPosit[318],bPosit;
string x1,x2,aIndex[9];
for (k3 = mStart; k3 <= mEnd; k3++)
{
x1 = mMove[k3]; aPosit[k3] = -1;
for (k2 = 0; k2 <= 8; k2++)
{
x2 = x1.substr(k2,1);
if (x2 == "0") x2 = "";
aIndex[k2] = x2;
}
bPosit = -1;
for (k2 = 0; k2 <= 21; k2+= 3)
{
x2 = "";
for (k1 = k2; k1 <= k2 + 2; k1++)
{
n1 = mCheck[k1];
if (aIndex[n1] == "") n2 = n1;
x2 = x2 + aIndex[n1];
}
if (x2 == "22")
{
aPosit[k3] = n2; goto aSkip;
}
if (x2 == "11") bPosit = n2;
}
if (bPosit != -1) aPosit[k3] = bPosit;
aSkip: k1 = 0;
if (aPosit[k3] != -1)
{
nMove[k3] = x1;
n1 = aPosit[k3];
nMove[k3].replace(n1,1,"2"); // User lost
}
else
{
n1 = x1.find("0",0);
nMove[k3] = x1;
nMove[k3].replace(n1,1,"2"); //User tied
}
}
}
int Move4a(string pMove)
{
int k1,n1,n2;
string x1,aMove;
for (k1 = 0; k1 <= 23; k1++)
{
n1 = mCheck[k1];
aMove = aMove + pMove.substr(n1,1);
n2 = (k1 + 1) % 3;
if (n2 == 0) aMove = aMove + " ";
}
n1 = aMove.find("222", 0);
return n1;
}
void LineUp5() // Total snapshots: 317
{
int k1,n1;
string x1,x2,aWin;
ofstream OutFile("TicB317.txt", ios::out);
for (k1 = 0; k1 <= mEnd; k1++)
{
x1 = nMove[k1];
n1 = Move4a(x1);
if (n1 == -1)
aWin = " c";
else
aWin = " w";
x2 = mMove[k1] + " " + x1 + aWin;
OutFile << x2 << endl;
}
OutFile.close();
}
Part 3
//This program compiles all possible Titatoe games using move by move
//method which is used as chess score e.g. A2A3 (pawn moves up)
//This program as player 1 and user as player 2
void aMain();
void SetUp1();
void Move2();
string Move2a(string);
int Move2b(string);
void Save3();
int mCheck[] = {0,1,2,3,4,5,6,7,8,0,3,6,1,4,7,2,5,8,0,4,8,2,4,6};
string mNum[] = {"0","1","2","3","4","5","6","7","8"},mMove[150],nMove[150];
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
SetUp1();
Move2();
Save3();
}
void SetUp1() // This program is depending on "TicA149.txt"
{ // It does not decode where to move
int k1; // by retrieving moves already made and storee in the txt list
string x1;
ifstream InFile("TicA149.txt", ios::in); //This is a snapshot list
for (k1 = 0; k1 <= 149; k1++)
{
getline(InFile,x1);
mMove[k1] = x1.substr(0,9);
nMove[k1] = x1.substr(10,9);
}
InFile.close();
}
void Move2() // aMove: user; bMove: this program
{
int k1,k2, k3,n1 = -1,n2,aCount, bCount = -1,aLen = 7;
string x1,x2, x3,x4,aMove[112], bMove[112], cMove[140];
string y1[] = {"40","41","42","43","45","46","47","48"};
// 40 means player 1 moves on cell 4 and player 2 moves on cell 0
for (k1 = 0; k1 <= aLen; k1++)
{
aMove[k1] = y1[k1];
bMove[k1] = Move2a(y1[k1]);
} //Move = 3th; array = 7; e.g.480
for (k2 = 0; k2 <= aLen; k2++)// Permutate all user's moves
{
x1 = bMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
n2 = x1.find(mNum[k1],0);
if (n2 == -1)
{
n1++;
aMove[n1] = x1 + mNum[k1];
}
}
}//Move = 4th; array = 47; e.g. 4807
aLen = n1;
for (k1 = 0; k1 <= aLen; k1++)
bMove[k1] = Move2a(aMove[k1]); //Move = 5th;
// 4081 is sent to Move2a(string); The function changed 4081 to
//snapshot "220010001", which is used as the key to retrieve
//a responding snapshot "221010001" and then change back to 40812
aCount = -1; bCount = -1;
for (k1 = 0; k1 <= aLen; k1++)
{
n1 = Move2b(bMove[k1]); // Check to see if there is already
if (n1 == -1) // a checkmate
{
aCount++;
aMove[aCount] = bMove[k1];
}// Move: 5th; continued 27
else
{
bCount++;
cMove[bCount] = bMove[k1];
}// Move: 5th; over games 19
}
aLen = aCount; n1 = -1;
for (k2 = 0; k2 <= aLen; k2++) // Permutate to 6th moves
{
x1 = aMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
n2 = x1.find(mNum[k1],0);
if (n2 == -1)
{
n1++;
bMove[n1] = x1 + mNum[k1];
}
} // Move: 6th; array: 111; e.g. 480765
}
aLen = n1; aCount = -1;
for (k1 = 0; k1 <= aLen; k1++)
{
x1 = Move2a(bMove[k1]); //Retrieve 7th moves
n1 = Move2b(x1); //Separate continued games from
if (n1 == -1) //Over-games
{
aCount++;
aMove[aCount] = x1;
} // Move 7th; continued 7; e.g. 4806715
else
{
bCount++;
cMove[bCount] = x1;
}// over games 123
}
aLen = aCount; n1 = -1;
for (k2 = 0; k2 <= aLen; k2++)
{
x1 = aMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
n2 = x1.find(mNum[k1],0);
if (n2 == -1)
{
n1++;
bMove[n1] = x1 + mNum[k1];
}
} // Move 8th, array 15; e.g. 48067153
}
aLen = n1; aCount = 131;
for (k2 = 0; k2 <= aLen; k2++)
{
x1 = bMove[k2];
for (k1 = 0; k1 <= 8; k1++)
if (x1.find(mNum[k1], 0) == -1) break;
x2 = x1 + mNum[k1]; n1 = Move2b(x2); // Separate won games
if (n1 != -1) // from tied games.
{
bCount++;
cMove[bCount] = x2;
}
else
{
aCount++;
cMove[aCount] = x2;
}
} // Move 9th; e.g. 4806715
aLen = aCount; // 0-131: won games; 132 - 139: tied games
//Total games: 139. The last 8 games are tied games. All other are
//won games for this program
ofstream OutFile("TicGameA139-8.txt", ios::out);
for (k1 = 0; k1 <= aLen; k1++)
OutFile << cMove[k1] << endl;
OutFile.close();
}
string Move2a(string pMove) // Input a move and return a counter move
{
int k1, n1 = 2, n2, aLen;
string aMove,bMove,x1,x2;
char c1[9];
aMove = "000000000"; //This is mold for making a snapshot
aLen = pMove.length();
pMove.copy(c1,aLen);
for (k1 = 0; k1 < aLen; k1++)
{ n1 = 3 - n1; // Alternation of 1 and 2
n2 = int(c1[k1]) - 48; //change char to int
aMove.replace(n2,1,mNum[n1]); //change int to character
} // and make it into a snapshot
for (k1 = 0; k1 <= 317; k1++)
if (aMove == mMove[k1]) break;
bMove = nMove[k1];
for (k1 = 0; k1 <= 8; k1++)
{
x1 = aMove.substr(k1,1); x2 = bMove.substr(k1,1);
if (x1 != x2) break;
}
x1 = pMove + mNum[k1];
return x1;
}
int Move2b(string pMove) // Input a move and return a yes or no
{ // (-1 or non -1) answer: game's over?
int k1, n1 = 2, n2, aLen; //e.g: move score: 40317 is an over game:
string aMove,aIndex[9]; // change 40317 into 210210010
char c1[9]; // Lineup into 210
aLen = pMove.length(); // 210
pMove.copy(c1,aLen); // 010 a triple 111 in second column
for (k1 = 0; k1 < aLen; k1++)
{
n1 = 3 - n1;
n2 = int(c1[k1]) - 48;
aIndex[n2] = mNum[n1];
}
for (k1 = 0; k1 <= 23; k1++)
{
n1 = mCheck[k1]; // Change a snapshot into a 8 units (of 3)
aMove = aMove + aIndex[n1];
n2 = (k1 + 1) % 3;
if (n2 == 0) aMove = aMove + " ";
}
n1 = aMove.find("111", 0);
return n1;
}
void Save3() //Decode game scores into gameboard: 40317
{ //become 2 1 -
int k1, k2,k3,n1, n2, aLen, aIndex[9]; // 2 1 -
string x1, bIndex[9]; // - 1 - Player 1 won
string Move1,aMove = "----------", bMove,cMove;
char c1[9];
ifstream InFile("TicGameA139-8.txt", ios::in); //Coded game score
ofstream OutFile("TicGameA139-8a.txt", ios::out); // 1-D formatted
for (k3 = 0; k3 <= 139; k3++) // move by move games.
{
InFile >> Move1;
bMove= aMove; cMove= "";
n1 = 2;
aLen = Move1.length();
Move1.copy(c1,aLen);
for (k2 = 0; k2 < aLen; k2++)
{
n1 = 3 - n1;
n2 = (int(c1[k2]) - 48);
aIndex[k2] = n2;
bIndex[k2] = mNum[n1];
}
for (k2 = 0; k2 < aLen; k2++)
{
n1 = aIndex[k2];
x1 = bIndex[k2];
bMove.replace(n1,1,x1);
for (k1 = 0; k1 <= 8; k1++)
cMove = cMove + bMove.substr(k1,1) + " ";
}
OutFile << cMove << endl;
}
OutFile.close();
InFile.close();
n1 = cMove.length() / 18; n2 = -6;
for (k2 = 0; k2 < n1; k2++)
{
for (k1 = 1; k1 <= 3; k1++)
{
n2 = n2 + 6;
cout << cMove.substr(n2,6) << endl;
}
cout << endl;
}
}
Part 4
//User as player 2; Program as player 1; Save3
// This program depends on "TicTac317.txt".It retrieves moves from this txt.
// For all explanation goto to see the prior subprogram
void aMain();
void SetUp1();
void Move2();
string Move2a(string);
int Move2b(string);
void Save3();
int mCheck[] = {0,1,2,3,4,5,6,7,8,0,3,6,1,4,7,2,5,8,0,4,8,2,4,6};
string mNum[] = {"0","1","2","3","4","5","6","7","8"},mMove[318],nMove[318];
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
SetUp1();
Move2();
Save3();
}
void SetUp1()
{
int k1;
string x1;
ifstream InFile("TicTac317.txt", ios::in);
for (k1 = 0; k1 <= 317; k1++)
{
getline(InFile,x1);
mMove[k1] = x1.substr(0,9); // Moves by player 1
nMove[k1] = x1.substr(10,9);// Moves by player 2
}
InFile.close();
}
void Move2()
{
int k1,k2,n1,n2,aCount, bCount = -1,aLen;
string x1,x2, aMove[315], bMove[315], cMove[457];
string y1[] = {"04","14","24","34","40","54","64","74","84"};
//Game score is based on cell numbers. 04 0 means cell 0 by player 1
for (k1 = 0; k1 <= 8; k1++) // 4 means cell 4 by player 2
bMove[k1] = y1[k1];
n1 = -1;
for (k2 = 0; k2 <= 8; k2++)
{
x1 = bMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
n2 = x1.find(mNum[k1],0);
if (n2 == -1)
{
n1++;
aMove[n1] = x1 + mNum[k1];
}
}
} // Move: 3rd; array: 62
aLen = n1;
for (k1 = 0; k1 <= aLen; k1++)
bMove[k1] = Move2a(aMove[k1]); //Move: 4th;
n1 = -1;
for (k2 = 0; k2 <= aLen; k2++)
{
x1 = bMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
n2 = x1.find(mNum[k1],0);
if (n2 == -1)
{
n1++;
aMove[n1] = x1 + mNum[k1]; }
} // Move: 5th; array: 314
}
aLen = n1;
for (k1 = 0; k1 <= aLen; k1++)
bMove[k1] = Move2a(aMove[k1]); // Move: 6th;
aCount = -1; bCount = -1;
for (k1 = 0; k1 <= aLen; k1++)
{
n1 = Move2b(bMove[k1]);
if (n1 == -1)
{
aCount++;
aMove[aCount] = bMove[k1];
} // 70; continued games
else
{
bCount++;
cMove[bCount] = bMove[k1];
} // 243; over games
}
aLen = aCount; n1 = -1;
for (k2 = 0; k2 <= aLen; k2++)
{
x1 = aMove[k2];
for (k1 = 0; k1 <= 8; k1++)
{
n2 = x1.find(mNum[k1],0);
if (n2 == -1)
{
n1++;
bMove[n1] = x1 + mNum[k1];
}
}
} // Move: 7th; 212
aLen = n1; aCount = 375;
for (k1 = 0; k1 <= aLen; k1++)
{
x1 = bMove[k1];
x2 = Move2a(x1);
n2 = Move2b(x2);
if (n2 != -1)
{
bCount++;
cMove[bCount] = x2;
}
else
{
aCount++;
cMove[aCount] = x2;
}
} // Move: 5th; Total 456 games
aLen = aCount;
ofstream OutFile("Tic456-81.txt", ios::out);
for (k1 = 0; k1 <= aLen; k1++)
OutFile << cMove[k1] << endl;
OutFile.close();
}
void Save3()
{
int k1, k2,k3,n1, n2, aLen, aIndex[9];
string x1, bIndex[9];
string Move1,aMove = "----------", bMove,cMove;
char c1[9];
ifstream InFile("Tic456-81.txt", ios::in);
ofstream OutFile("Tic456-81a.txt", ios::out);
for (k3 = 0; k3 <= 456; k3++)
{
InFile >> Move1;
bMove= aMove; cMove= "";
n1 = 2;
aLen = Move1.length();
Move1.copy(c1,aLen);
for (k2 = 0; k2 < aLen; k2++)
{
n1 = 3 - n1;
n2 = (int(c1[k2]) - 48);
aIndex[k2] = n2;
bIndex[k2] = mNum[n1];
}
for (k2 = 0; k2 < aLen; k2++)
{
n1 = aIndex[k2];
x1 = bIndex[k2];
bMove.replace(n1,1,x1);
for (k1 = 0; k1 <= 8; k1++)
cMove = cMove + bMove.substr(k1,1) + " ";
}
OutFile << cMove << endl;
}
OutFile.close();
InFile.close();
n1 = cMove.length() / 18; n2 = -6;
for (k2 = 0; k2 < n1; k2++)
{
for (k1 = 1; k1 <= 3; k1++)
{
n2 = n2 + 6;
cout << cMove.substr(n2,6) << endl;
}
cout << endl;
}
}
void Save3(string pMove)
{
int k1, n1 = 2, n2, aLen;
string x1, aMove = "- - - - - - - - - - ";
char c1[9];
cout << pMove << endl;
aLen = pMove.length();
pMove.copy(c1,aLen);
for (k1 = 0; k1 < aLen; k1++)
{
n1 = 3 - n1;
n2 = (int(c1[k1]) - 48) * 2;
aMove.replace(n2,1,mNum[n1]);
}
for (k1 = 0; k1 <= 12; k1+= 6)
cout << aMove.substr(k1,6) << endl;
cout << endl;
}
int Move2b(string pMove)
{
int k1, n1 = 2, n2, aLen;
string aMove,aIndex[9];
char c1[9];
aLen = pMove.length();
pMove.copy(c1,aLen);
for (k1 = 0; k1 < aLen; k1++)
{
n1 = 3 - n1;
n2 = int(c1[k1]) - 48;
aIndex[n2] = mNum[n1];
}
for (k1 = 0; k1 <= 23; k1++)
{
n1 = mCheck[k1];
aMove = aMove + aIndex[n1];
n2 = (k1 + 1) % 3;
if (n2 == 0) aMove = aMove + " ";
}
n1 = aMove.find("222", 0);
return n1;
}
string Move2a(string pMove)
{
int k1, n1 = 2, n2, aLen;
string x1,x2,aMove = "000000000",bMove;
char c1[9];
aLen = pMove.length();
pMove.copy(c1,aLen);
for (k1 = 0; k1 < aLen; k1++)
{ n1 = 3 - n1;
n2 = int(c1[k1]) - 48;
aMove.replace(n2,1,mNum[n1]);
}
for (k1 = 0; k1 <= 317; k1++)
if (aMove == mMove[k1]) break;
bMove = nMove[k1];
for (k1 = 0; k1 <= 8; k1++)
{
x1 = aMove.substr(k1,1); x2 = bMove.substr(k1,1);
if (x1 != x2) break;
}
x1 = pMove + mNum[k1];
return x1;
}
Part 5
//Let a user plays against this program. A user types a cell number and
//the program returns a counter move. No user defeats this program
//The program depends 2 textfiles, which function as 2 database created
// and stored in previous 2 sub-programs. This program, in fact, a
// simple information retrieval.
void aMain();
void Play1(); // User as Player 1
void Play2(); // User as Player 2
void ShowX(string,string);//Display the game move by move in 2-D game board.
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
int n1;
string x1 =
"Play Tic Game against This program? Type 1 to be first mover Else type 2: ";
cout << x1;
cin >> n1;
if (n1 == 1)
Play1();
else
Play2();
}
void Play1()
{
int k1,k2,n1;
string x1,x2,aMove[318],bMove[318],aWin[318], bWin;
string aGame = "000000000", bGame;
ifstream InFile("TicB317.txt", ios::in);
for (k1 = 0; k1 <= 317; k1++)
{
getline(InFile,x1);
aMove[k1] = x1.substr(0,9); bMove[k1] = x1.substr(10,9);
aWin[k1] = x1.substr(20,1);
}
InFile.close();
ShowX("123456789",aGame);
for (k2 = 1; k2 <= 4; k2++)
{
cout << "To play a Tic Game, enter a number (1-9) now: ";
cin >> n1;
aGame.replace(n1-1,1,"1");
for (k1 = 0; k1 <= 317; k1++)
if (aGame == aMove[k1]) break;
bGame = bMove[k1]; bWin = aWin[k1];
ShowX(aGame,bGame);
aGame = bGame;
if (bWin == "w") break;
}
if (bWin == "c")
cout << "Game's over.You tied.";
else
cout << "Game's over.You lost.";
// The game's dipay:
// 123 - - - 1 - - 1 - - 1 - - 1 2 - 1 2 -
// 456 - - - - - - - 2 - 1 2 - 1 2 - 1 2 -
// 789 - - - - - - - - - - - - - - - 1 - - checkmate
}
void Play2()
{
int k1,k2,n1;
string x1,aMove[150],bMove[150],aWin[150], bWin;
string aGame = "000010000", bGame;
ifstream InFile("TicA149.txt", ios::in);
for (k1 = 0; k1 <= 149; k1++)
{
getline(InFile,x1);
aMove[k1] = x1.substr(0,9); bMove[k1] = x1.substr(10,9);
aWin[k1] = x1.substr(20,1);
}
InFile.close();
ShowX("123456789",aGame);
for (k2 = 1; k2 <= 4; k2++)
{
cout << "To play a Tic Game, enter a number (1-9) now: ";
cin >> n1;
aGame.replace(n1-1,1,"2");
for (k1 = 0; k1 <= 149; k1++)
if (aGame == aMove[k1]) break;
bGame = bMove[k1]; bWin = aWin[k1];
ShowX(aGame,bGame);
aGame = bGame;
if (bWin == "w") break;
}
if (bWin == "c")
cout << "Game's over.You tied.";
else
cout << "Game's over.You lost.";
}
void ShowX(string pMove,string qMove)
{
int k1,k2;
string x1, x2; // aShow & bShow are 2-D game board.
string aShow[] = {"-","-","-","-","-","-","-","-","-"};
string bShow[] = {"-","-","-","-","-","-","-","-","-"};
for (k1 = 0; k1 <= 8; k1++)
{
x1 = pMove.substr(k1,1);
if (x1 != "0") aShow[k1] = x1;
x1 = qMove.substr(k1,1);
if (x1 != "0") bShow[k1] = x1;
}
for (k2 = 0; k2 <= 6; k2+= 3)
{
x1 = ""; x2 = "";
for (k1 = k2; k1 <= k2+ 2; k1++)
{
x1 = x1 + aShow[k1] + " ";
x2 = x2 + bShow[k1] + " ";
}
cout << x1 << " " << x2 << endl;
}
cout << endl;
}
***** 10
Coding 8-Queen Series
(Solving problems by permutation)
Put 8 queens on the chessboard with one
condition: Not a single queen attacks any other 7.
Permutate 92 possible 8-Queen Series
Overview
Use one int array[0-63] and another string array[0-63] to represent the chessboard;
Use 1-8 to represent the 8 queens on the chessboard
Cell Number Int string
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
8 9 10 11 12 13 14 15 8 9 : ; < = > ?
16 17 18 19 20 21 22 23 @ A B C D E F G
24 25 26 27 28 29 30 31 H I J K L M N O
32 33 34 35 36 37 38 39 P Q R S T U V W
40 41 42 43 44 45 46 47 X Y Z [ \ ] ^ -
48 49 50 51 52 53 54 55 ` a b c d e f g
56 57 58 59 60 61 62 63 h i j k l m n o
Controlling Lines
Vertical Forward Diagonal Backward Diagonal
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
0 1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 8 0 1 2 3 4 5 6
0 1 2 3 4 5 6 7 2 3 4 5 6 7 8 9 9 8 0 1 2 3 4 5
0 1 2 3 4 5 6 7 3 4 5 6 7 8 9 10 10 9 8 0 1 2 3 4
0 1 2 3 4 5 6 7 4 5 6 7 8 9 10 11 11 10 9 8 0 1 2 3
0 1 2 3 4 5 6 7 5 6 7 8 9 10 11 12 12 11 10 9 8 0 1 2
0 1 2 3 4 5 6 7 6 7 8 9 10 11 12 13 13 12 11 10 9 8 0 1
0 1 2 3 4 5 6 7 7 8 9 10 11 12 13 14 14 13 12 11 10 9 8 0
Cell 0's control Line: 89@BHKPTX]`fho (8,9,16,18,24,27,32,36,40,45,48,54,56,63)
The first 8-queen series: 0> aQueen[k1];
InFile.close();
//Failure test by creating an error to see if it's picked up.
// x2 = aQueen[79]
//aQueen[79] = aQueen[79].substr(0,7) + "o"; create an error here
for (k3 = 0; k3 <= 91; k3++) // Check if any 8-queen series has mutual attack problem
{
x1 = aQueen[k3]; x1.copy(c1,8);
for (k2 = 0; k2 <= 7; k2++)
{
aIndex[k2] = int(c1[k2]) - 48; // Use an arabic and an ASCII to represent
bIndex[k2] = x1.substr(k2,1); // a cell. Arabic as the key to retrieve
} // the control cells, which is ASCII, and ASCII to see if Cell X
for (k2 = 0; k2 <= 6; k2++) // is already in another cell's control cell list.
{
x1 = bIndex[k2];
for (k1 = k2 + 1; k1 <= 7; k1++)
{
n1 = aIndex[k1];
if (mIndex[n1].find(x1,0) != -1)
cout << k3 << " is faulty " << k2 << " attacks " << k1 << endl;
//Series 79 has an error. Because cell 1 and 3 attack cell 7.
}
}
}
//aQueen[79] = x2;
// x2 = aQueen[90];
// aQueen[90] = aQueen[9]; // Check if the duplicated aMove[90] is picked up.
for (k2 = 0; k2 <= 91; k2++)
{
x1 = aQueen[k2];
for (k1 = k2 + 1; k1 <= 91; k1++)
if (x1 == aQueen[k1]) cout << k2 << " duplicates " << k1 << endl;
}
// aQueen[90] = x2;
cout << "To print onscreen an 8-queen series, enter a number(0-91): ";
cin >> n1;
aQueen[n1].copy(c1,8); // Change string to char and then to int
x1 = "";
for (k1 = 0; k1 <= 63; k1++) // Create a mold
x1 = x1 + "- ";
for (k1 = 0; k1 <= 7; k1++)
{
n1 = (int(c1[k1])- 48) * 2;
x1.replace(n1,1,mNum[k1+1]); //Pour data in the mold
}
n1 = 0;
for (k1 = 0; k1 <= 7; k1++) // Add spaces and line up to 2D
{
cout << " " + x1.substr(n1,16) << endl;
n1 = n1 + 16;
}
}
void Print3()// Print 92 8-queen series in 2-D with some formatting
{ // in a text file. Font must be set to Courier New
int k1,k2,k3,n1;
string x1,x2,aMove[92], bMove[4],aMold, bMold;
char c1[8];
ifstream InFile("Queen91.txt", ios::in);
for (k1 = 0; k1 <= 91; k1++)
InFile >> aMove[k1];
InFile.close();
for (k1 = 0; k1 <= 63; k1++)
aMold = aMold + "- ";
for (k2 = 0; k2 <= 91; k2++)
{
bMold = aMold; // Make 92 copies of the chessboard
aMove[k2].copy(c1,8);
for (k1 = 0; k1 <= 7; k1++)
{
n1 = (int(c1[k1])- 48) * 2; // Convert 8 ASCII to 8 arabic and
bMold.replace(n1,1,mNum[k1+1]); // use them as positions in which
} // to plant 1-8 numbers
aMove[k2] = bMold;
}
n1 = -1;
for (k2 = 0; k2 <= 88; k2+= 4) // Formatting: divide 92 8-queen series into
{ // 23 groups and 4 series per section.
x1 = "";
for (k1 = k2; k1 <= k2 + 3; k1++)
x1 = x1 + aMove[k1];
n1 = n1 + 1;
aMove[n1] = x1;
}
ofstream OutFile("Group22.txt", ios::out);
OutFile << " 92 8-queen series (divided into 23 groups of 4" << endl;
for (k3 = 0; k3 <= 22; k3++)
{
OutFile << "Group " << k3 << endl;
n1 = 0; x1 = aMove[k3];
for (k2 = 0; k2 <= 3; k2++)
{
bMove[k2] = x1.substr(n1,128); // A series is 128 in length
n1 = n1 + 128;
}
for (k2 = 0; k2 <= 112; k2+= 16)
{
x2 = "";
for (k1 = 0; k1 <= 3; k1++)
x2 = x2 + bMove[k1].substr(k2,16) + " "; // Add 3 spaces betwee
OutFile << x2 << endl; // 2 series.
}
OutFile << "" << endl;
}
OutFile.close();
}
***** 11
//Coding conversion among 3-type of numbers (Arabic, English and Roman
//Compiling time: 1 minute
Part 1: Compile English and Roman lists, which are used as textfile-form
Part 2: Input and Output one type of number to another type of numbers.
Part 1
string mEng[1001];
int nEng2[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
30,40,50,60,70,80,90,100,1000};
string nEng1[] = {"One","Two","Three","Four","Five","Six","Seven",
"Eight","Nine","Ten","Eleven","Twelve","Thirteen","Fourteen",
"Fifteen","Sixteen","Seventeen","Eighteen","Nineteen","Twenty",
"Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety",
"Hundred","Thousand"};
void aMain();
void SetUp();
void Eng1a(); //Non-formatted (1-999999) compiling
void Eng1b(); //Formatted (1-999999)
void Eng2a(); //Non-formatted (1-999999)
void Eng2b(); //Formatted (1-999999)
string Taila(int); // Tail means the last 2 digits of an Arabic number
string Tailb(int); // In English, 19 if one word (Nineteen), 91 is 2 words
void L1Check3(); // Is list 1 error free?
void L2Check4(); // Is list 2 error free?
void L12Check5(); //2 sets of lists are made. They must match eactly
void Rom6(); //Roman numeral (1-3999) compiling
void CheckRom7(); // Converse all the Romans back to Arab. Do they match?
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain()
{
int k1,k2,k3,n1,n2;
string x1, x2;
SetUp();
Eng1a();
Eng1b();
Eng2a();
Eng2b();
L1Check3();
L2Check4();
L12Check5();
Rom6();
CheckRom7();
}
void SetUp()
{
int k1,n1;
for (k1 = 0; k1 <= 28; k1++)
{
n1 = nEng2[k1]; mEng[n1] = nEng1[k1];
}
}
// Compile a list of 1-999,999 English numbers
void Eng1a() // No formatting: 129 = OneHundredTwentyNine
{ // Use to input English and output Arabic quickly
int k1,k2,n1,n2;
string x1,x2,aEng[100000], bEng[10000];
for (k1 = 1; k1 <= 90; k1++) // Finish 1-19 and 10-90
if (mEng[k1] != "") aEng[k1] = mEng[k1];
for (k2 = 20; k2 <= 90; k2+= 10) // Finish 21 - 99
{
x1 = aEng[k2];
for (k1 = 1; k1 <= 9; k1++)
{
n1 = k2 + k1;
aEng[n1] = x1 + aEng[k1];
}
}
for (k2 = 1; k2 <= 9; k2++) // Compile 100 - 999
{
x1 = aEng[k2] + "Hundred";
for (k1 = 0; k1 <= 99; k1++)
{
n1++;
aEng[n1] = x1 + aEng[k1];
}
}
n1 = 0;
for (k1 = 1000; k1 <= 9000; k1+= 1000) // Compile 1000 - 9000
{
n1++;
aEng[k1] = aEng[n1] + "Thousand";
}
for (k2 = 11; k2 <= 91; k2+= 10)// Compile 1100 - 9900
{
for (k1 = k2; k1 <= k2 + 8; k1++)
{
n1 = k1 * 100;
aEng[n1] = aEng[k1] + "Hundred";
}
}
for (k2 = 1000; k2 <= 9900; k2+= 100) // Compile 1001 - 9999
{
x1 = aEng[k2];
for (k1 = 1; k1 <= 99; k1++)
{
n1 = k2 + k1;
aEng[n1] = x1 + aEng[k1];
}
}
for (k2 = 1000; k2 <= 9900; k2+= 100) // Compile 1000 - 9999
{
n1 = k2 / 1000; x1 = aEng[n1] + "Thousand";
n1 = (k2 % 1000) / 100; // 1000 = OneThousand
if (n1 != 0) x1 = x1 + aEng[n1] + "Hundred";
bEng[k2] = x1; // 1100 = ElevenHundred
for (k1 = 1; k1 <= 99; k1++)
{
n1 = k2 + k1;
bEng[n1] = x1 + aEng[k1];
}
}
n1 = 9;
for (k2 = 10000; k2 <= 99000; k2+= 1000) //Compile 10000 - 99999
{
n1++; x1 = aEng[n1] + "Thousand";
for (k1 = 0; k1 <= 999; k1++)
{
n2 = k2 + k1; aEng[n2] = x1 + aEng[k1];
}
}
ofstream OutFile("EngNum1a.txt", ios::out);
for (k2 = 1; k2 <= 99999; k2++) // Save 1 - 99999
OutFile << aEng[k2] << endl;
for (k2 = 1; k2 <= 9; k2++) // Save 100000 - 999999
{
x1 = aEng[k2] + "Hundred";
for (k1 = 0; k1 <= 999; k1++)
{
x2 = x1 + "Thousand" + aEng[k1];
OutFile << x2 << endl;
}
for (k1 = 1000; k1 <= 9999; k1++)
{
x2 = x1 + bEng[k1];
OutFile << x2 << endl;
}
for (k1 = 10000; k1 <= 99999; k1++)
{
n1 = k2 * 100000 + k1;
x2 = x1 + aEng[k1];
OutFile << x2 << endl;
}
}
OutFile.close();
}
// Compile a list of 1-999,999 English numbers
void Eng1b() // For inputing Arabic and outputing English (formatted)
{ // 100221 = One Hundred Thousand, Two Hundred and Twenty One
int k1,k2,n1, n2 = -1, n3,aCount;
string x1,x2,x3,x4,aEng[100000], bEng[10000];
for (k1 = 1; k1 <= 90; k1++)
if (mEng[k1] != "") aEng[k1] = mEng[k1];
for (k2 = 20; k2 <= 90; k2+= 10) // 1- 99
{
x1 = aEng[k2] + " ";
for (k1 = 1; k1 <= 9; k1++)
{
n1 = k2 + k1;
aEng[n1] = x1 + aEng[k1];
}
}
n1 = 0;
for (k2 = 100; k2 <= 900; k2+= 100)
{
n1++;
x1 = aEng[n1] + " Hundred";
aEng[k2] = x1;
x1 = x1 + " And " ;
for (k1 = 1; k1 <= 99; k1++)
{
n2 = k2 + k1;
aEng[n2] = x1 + aEng[k1];
}
}
n1 = 0;
for (k1 = 1000; k1 <= 9000; k1+= 1000)
{
n1++;
aEng[k1] = aEng[n1] + " Thousand";
}
for (k2 = 11; k2 <= 91; k2+= 10)
{
for (k1 = k2; k1 <= k2 + 8; k1++)
{
n1 = k1 * 100;
aEng[n1] = aEng[k1] + " Hundred";
}
}
for (k2 = 1000; k2 <= 9900; k2+= 100)
{
x1 = aEng[k2] + " And ";
for (k1 = 1; k1 <= 99; k1++)
{
n1 = k2 + k1;
aEng[n1] = x1 + aEng[k1];
}
}
n1 = 9;
for (k2 = 10000; k2 <= 99000; k2+= 1000)
{
n1++;
x1 = aEng[n1] + " Thousand";
aEng[k2] = x1;
for (k1 = 1; k1 <= 99; k1++)
{
n2 = k2 + k1;
aEng[n2] = x1 + " And " + aEng[k1];
}
for (k1 = 100; k1 <= 999; k1++)
{
n2 = k2 + k1;
if (k1 % 100 == 0)
aEng[n2] = x1 + " And " + aEng[k1];
else
aEng[n2] = x1 + ", " + aEng[k1];
}
}
ofstream OutFile("EngNum1b.txt", ios::out);
for (k1 = 1; k1 <= 99999; k1++)
OutFile << aEng[k1] << endl;
aCount = 0;
for (k2 = 100000; k2 <= 900000; k2+= 100000)
{
aCount++;
x1 = aEng[aCount] + " Hundred"; x2 = x1 + " Thousand";
OutFile << x2 << endl;
for (k1 = 1; k1 <= 99; k1++)
{
x3 = x2 + " And " + aEng[k1];
OutFile << x3 << endl;
}
for (k1 = 100; k1 <= 999; k1++)
{
if (k1 % 100 == 0)
x3 = x2 + " And " + aEng[k1];
else
x3 = x2 + ", " + aEng[k1];
OutFile << x3 << endl;
}
for (k1 = 1000; k1 <= 1099; k1++)
{
x3 = x1 + " And " + aEng[k1];
OutFile << x3 << endl;
}
for (k1 = 1100; k1 <= 9999; k1++)
{
x3 = ""; x2 = "";
n1 = k1 / 1000;
x2 = x1 + " And " + aEng[n1] + " Thousand";
n1 = (k1 % 1000) / 100; n2 = k1 % 100;
if (n1 == 0)
{
if (n2 == 0)
x3 = x2;
else
x3 = x2 + " And " + aEng[n2];
}
else // n1 != 0
{
if (n2 == 0)
x3 = x2 + " And " + aEng[n1] + " Hundred";
else
x3 = x2 + ", " + aEng[n1] + " Hundred And " + aEng[n2];
}
OutFile << x3 << endl;
}
for (k1 = 10000; k1 <= 99999; k1++)
{
x2 = x1 + " And " + aEng[k1];
OutFile << x2 << endl;
}
}
OutFile.close();
}
void Eng2a()
{
int k1,n1, n2,aAra;
string x1,aTail; // aTail is the last 2 digits numbers. e.g, 34 in 1234
ofstream OutFile("EngNum2a.txt", ios::out);
for (k1 = 1; k1 <= 999999; k1++)
{
aTail = "";
n1 = k1 % 100; if(n1 != 0) aTail = Taila(n1);
aAra = k1 / 100;
if (aAra == 0) // 1, 10, 11
{
x1 = aTail; goto aBottom;
}
else if (aAra < 10) //100
{
x1 = mEng[aAra] + "Hundred" + aTail;
}
else if (aAra < 100) // 1000
{
if (aAra % 10 == 0)
{
n1 = aAra / 10;
x1 = mEng[n1] + "Thousand";
}
else
{
x1 = Taila(aAra) + "Hundred";
}
x1 = x1 + aTail;
}
else if (aAra < 1000) // 10000
{
n1 = aAra / 10; x1 = Taila(n1) + "Thousand";
n2 = aAra % 10;
if (n2 != 0) x1 = x1 + mEng[n2] + "Hundred";
x1 = x1 + aTail;
}
else // 100,000
{
n1 = aAra / 1000; x1 = mEng[n1] + "Hundred";
n1 = (aAra % 1000) / 10; n2 = aAra % 10;
if (n1 == 0) // 11000
{
if (n2 == 0) //100
x1 = x1 + "Thousand";
else
x1 = x1 + "Thousand" + mEng[n2] + "Hundred";
}
else // n1 != 0
if (n2 == 0) //100
x1 = x1 + Taila(n1) + "Thousand";
else
x1 = x1 + Taila(n1) + "Thousand" + mEng[n2] + "Hundred";
x1 = x1 + aTail;
}
aBottom: n1 = 0;
OutFile << x1 << endl;
}
OutFile.close();
}
void Eng2b()
{
int k1,n1, n2,aAra;
string x1,aTail;
ofstream OutFile("EngNum2b.txt", ios::out);
for (k1 = 1; k1 <= 999999; k1++)
{
aTail = "";
n1 = k1 % 100; if(n1 != 0) aTail = Tailb(n1);
aAra = k1 / 100;
if (aAra == 0) // 1, 10, 11
{
x1 = aTail; goto aBottom;
}
else if (aAra < 10) //100
{
x1 = mEng[aAra] + " Hundred";
if (aTail != "") x1 = x1 + " And " + aTail;
}
else if (aAra < 100) // 1000
{
if (aAra % 10 == 0)
{
n1 = aAra / 10;
x1 = mEng[n1] + " Thousand";
}
else
{
x1 = Tailb(aAra) + " Hundred";
}
if (aTail != "") x1 = x1 + " And " + aTail;
}
else if (aAra < 1000) // 10000
{
n1 = aAra / 10; x1 = Tailb(n1) + " Thousand";
n2 = aAra % 10;
if (n2 == 0)
{
if (aTail != "")
x1 = x1 + " And " + aTail;
}
else
{
if (aTail == "")
x1 = x1 + " And " + mEng[n2] + " Hundred";
else
x1 = x1 + ", " + mEng[n2] + " Hundred And " + aTail;
}
}
else // 100,000
{
n1 = aAra / 1000; x1 = mEng[n1] + " Hundred";
n1 = (aAra % 1000) / 10; n2 = aAra % 10;
if (n1 == 0) // 11000
{
if (n2 == 0) //100
{
if (aTail == "")
x1 = x1 + " Thousand";
else
x1 = x1 + " Thousand And " + aTail;
}
else
{
if (aTail == "")
x1 = x1 + " Thousand And " + mEng[n2] +
" Hundred";
else
x1 = x1 + " Thousand, " + mEng[n2] +
" Hundred And " + aTail;
}
}
else // n1 != 0
{
if (n2 == 0)
{
if (aTail == "")
{
x1 = x1 + " And " + Tailb(n1) + " Thousand";
}
else // aTail != ""
x1 = x1 + " And " + Tailb(n1) + " Thousand And " + aTail;
}
else // n1 != 0 and n2 !- 0
{
if (aTail == "")
x1 = x1 + " And " + Tailb(n1) + " Thousand And " +
mEng[n2] + " Hundred";
else // aTail != "";
x1 = x1 + " And " + Tailb(n1) + " Thousand, " +
mEng[n2] + " Hundred And " + aTail;
}
}
}
aBottom: n1 = 0;
OutFile << x1 << endl;
}
OutFile.close();
}
string Taila(int pAra) // For no format English numbers
{
int n1,n2;
string x1;
n1 = pAra;
if (n1 < 21 || n1 % 10 == 0)
x1 = mEng[n1]; // 1-20 and 30-90: One word (19 = Nineteen)
else
{
n2 = n1 % 10; n1 = n1 - n2; //21: Two words (29 = Twenty Nine)
x1 = mEng[n1] + mEng[n2];
}
return x1;
}
string Tailb(int pAra) // For formatted English numbers
{
int n1,n2;
string x1;
n1 = pAra;
if (n1 < 21 || n1 % 10 == 0)
x1 = mEng[n1];
else
{
n2 = n1 % 10; n1 = n1 - n2;
x1 = mEng[n1] + " " + mEng[n2];
}
return x1;
}
void L1Check3() // L1 = List 1: no space and no format
{
int k1,k2,k3,n1,n2, aLen,aSum, bSum,aAra[15];
string x1,x2,x3,Eng1, Eng2[15];
// For no space number: 1234 is TwelveHundredThirtyFour
// word separator is a letter < "a" (a capitalized letter)
//1. locate those letters; T,H,T,F
//2. Insert spaces Twelve Hundred Thirty Four
// 3.Swap Eng with Ara: 12, 100, 30, 4
// 4. 12 <= 100, time them, 100 > 30, add them and 30 > 4, add them
// 1200 + 30 + 4 = 1234
// 100234 = 1, 100, 1000,2, 100, 30, 4
// aSum = 1 * 100 * 1000; bSum = 2 * 100 + 30 + 4. aSum + bSum = 100234
ifstream InFile("EngNum1a.txt", ios::in);
for (k3 = 1; k3 <= 999999; k3++)
{
InFile >> x1;
aLen = x1.length() - 1;
Eng1 = x1.substr(0,1);
for (k2 = 1; k2 <= aLen; k2++)
{
x2 = x1.substr(k2,1);
if (x2 < "a") x2 = " " + x2;
Eng1 = Eng1 + x2;
}
Eng1 = Eng1 + " ";
n2 = -1;
for (k2 = 0; k2 <= 10; k2++)
{
n1 = n2 + 1;
n2 = Eng1.find(" ",n1);
if (n2 == -1) break;
Eng2[k2] = Eng1.substr(n1,n2 - n1);
}
aLen = k2 -1;
for (k2 = 0; k2 <= aLen; k2++)
{
x1 = Eng2[k2];
for (k1 = 0; k1 <= 28; k1++)
{
if (x1 == nEng1[k1]) break;
}
aAra[k2] = nEng2[k1];
}
if (aLen == 0)
{
aSum = aAra[0]; goto aBottom;
}
n1 = aAra[0]; aSum = 0; bSum = 0;
for (k1 = 1; k1 <= aLen; k1++)
{
n2 = aAra[k1];
if (n1 <= n2)
aSum = n1 * n2;
else
aSum = n1 + n2;
n1 = aSum;
if (n2 == 1000 && k1 < aLen)
{
n1 = 1; bSum = aSum;
}
}
aSum = aSum + bSum;
aBottom: n1 = 0;
if (k3 != aSum)
cout << "Error in: " << k3 << " " << Eng1 << " " << aSum << endl;
}
InFile.close();
}
void L2Check4() // Check List2: formatted English numbers
{ // Replace format words with single spaces.
int k1,k2,k3,n1,n2,aSum, bSum,aAra[11], aLen[] = {2,1,5,2}, bLen;
string x1,aWord[] = {", ", "-", " And ", " "},bWord,Eng1, Eng2[13];
ifstream InFile("EngNum1b.txt", ios::in);
for (k3 = 1; k3 <= 999999; k3++)
{
getline(InFile, Eng1);
Eng1 = Eng1 + " ";
for (k2 = 0; k2 <= 3; k2++)
{
n2 = -1;
bWord = aWord[k2]; bLen = aLen[k2];
for (k1 = 1; k1 <= 7; k1++)
{
n1 = n2 + 1;
n2 = Eng1.find(bWord,n1);
if (n2 == -1) break;
Eng1.replace(n2,bLen," "); // Space as separators
}
}
n2 = -1;
for (k2 = 0; k2 <= 10; k2++)
{
n1 = n2 + 1;
n2 = Eng1.find(" ",n1);
if (n2 == -1) break;
Eng2[k2] = Eng1.substr(n1,n2- n1);
}
bLen = k2 -1;
for (k2 = 0; k2 <= bLen; k2++)
{
x1 = Eng2[k2];
for (k1 = 0; k1 <= 28; k1++) // Change English to Arabic
{
if (x1 == nEng1[k1]) break;
}
aAra[k2] = nEng2[k1];
}
if (bLen == 0)
{
aSum = aAra[0]; goto aBottom;
}
n1 = aAra[0]; aSum = 0; bSum = 0;
for (k1 = 1; k1 <= bLen; k1++)
{
n2 = aAra[k1];
if (n1 <= n2)
aSum = n1 * n2;
else
aSum = n1 + n2;
n1 = aSum;
if (n2 == 1000 && k1 < bLen)//Retart timing and adding
{
n1 = 1; bSum = aSum;
}
}
aSum = aSum + bSum;
aBottom: n1 = 0;
if (k3 != aSum)
cout << "Error in " << k3 << " " << Eng1 << " " << aSum << endl;
}
InFile.close();
}
void L12Check5() // Compare 1a with 2a and 1b with 2b.
{ // They must be exactly the same
int k1,k2,k3,n1,n2,aSum, bSum,aAra[11], bLen;
string x1,x2,bWord,Eng1, Eng2[13];
ifstream aInFile("EngNum1a.txt", ios::in);
ifstream bInFile("EngNum2a.txt", ios::in);
for (k1 = 1; k1 <= 999999; k1++)
{
aInFile >> x1;
bInFile >> x2;
if (x1 != x2)
cout << "Error in " << k1 << " " << x1 << " " << x2 << endl;
}
aInFile.close();
bInFile.close();
ifstream cInFile("EngNum1b.txt", ios::in);
ifstream dInFile("EngNum2b.txt", ios::in);
for (k1 = 1; k1 <= 999999; k1++)
{
getline(cInFile, x1);
getline(dInFile, x2);
if (x1 != x2)
cout << "Error in " << k1 << " " << x1 << " " << x2 << endl;
}
cInFile.close();
dInFile.close();
}
void Rom6()// Compile a list of 1-3999 Roman numerals
{ // Max: 1-3999 (I - MMMCMXCIX. Windows ASCII does not
int k1,k2, n1; // support Rom 5000 and above
int m1[] = {1,2,3,4,5,6,7,8,9,10,20,30,40,50,60,70,80,90,
100,200,300,400,500,600,700,800,900,1000,2000,3000};
string m2[] = {"I","II","III","IV","V","VI","VII","VIII","IX","X","XX",
"XXX","XL","L","LX","LXX","LXXX","XC","C","CC","CCC",
"CD","D","DC","DCC","DCCC","CM","M","MM","MMM"};
string x1,aRom[4001];
for (k1 = 0; k1 <= 29; k1++)
{
n1 = m1[k1];
aRom[n1] = m2[k1];
}
for (k2 = 10; k2 <= 90; k2+= 10)
{
x1 = aRom[k2];
for (k1 = 1; k1 <= 9; k1++)
{
n1 = k2 + k1;
aRom[n1] = x1 + aRom[k1];
}
}
for (k2 = 100; k2 <= 900; k2+= 100)
{
x1 = aRom[k2];
for (k1 = 1; k1 <= 99; k1++)
{
n1 = k2 + k1;
aRom[n1] = x1 + aRom[k1];
}
}
for (k2 = 1000; k2 <= 3000; k2+= 1000)
{
x1 = aRom[k2];
for (k1 = 1; k1 <= 999; k1++)
{
n1 = k2 + k1;
aRom[n1] = x1 + aRom[k1];
}
}
ofstream OutFile("Rnum3999.txt", ios::out);
for (k1 = 1; k1 <= 3999; k1++)
OutFile << aRom[k1] << endl;
OutFile.close();
}
void CheckRom7() // Converse all roman nums back to Ara and all match
{
int k1,k2, k3,n1, n2, aSum, aLen;
int bRom[] = {1,5,10,50,100,500,1000}, aAra[15] = {0};
char aRom[] = {'I','V','X','L','C','D','M'}, c1,Rom1[15];
string x1; // C is in aRom[4] and bRom[4] = 100
ifstream InFile("Rnum3999.txt", ios::in);
for (k3 = 1; k3 <= 3999; k3++)
{
InFile >> x1;
aLen = x1.length();
x1.copy(Rom1,aLen); aLen = aLen -1;
for (k2 = 0; k2 <= aLen; k2++)
{
c1 = Rom1[k2];
for (k1 = 0; k1 <= 6; k1++)
if (c1 == aRom[k1]) break;
aAra[k2] = bRom[k1]; // Change Rom letters to Arabic
}
if (aLen == 0)
{
aSum = aAra[aLen]; goto aBottom;
}
aSum = aAra[aLen];
for (k2 = 0; k2 < aLen; k2++)
{
n1 = aAra[k2]; n2 = aAra[k2+ 1];
if (n1 < n2) n1 = -n1; //Value comparison is done here.
aSum = aSum + n1;
}
aBottom: n1 = 0;
if (k3 != aSum)
cout << "Error in " << k3 << ": " << aSum << endl;
}
InFile.close();
//How to add up roman numbers
//MMCMXCIX (2999) = 1000,1000, 100,1000,10,100,1,10
//1000 < 1000: false 1000 = 1000
//1000 < 100: false 1000 = 1000
//100 < 1000: true 100 = -100
//1000 < 10: false 1000 = 1000
//10 < 100: true 10 = -10
//100 < 1: false 100 = 100
//1 < 10: true 1 = -1
//10 = 10
// aSum = 1000 + 1000 + (-100) + 1000 + (-10) + 100 + (-1) + 10: 2999
}
Part 2
void aMain();
string AraToEng(int);
string AraToRom(int);
int EngToAra(string);
int RomToAra(string);
int main(int argc, char** argv)
{
aMain();
exit(0);
system("PAUSE");
return 0;
}
void aMain() // Windows' ASCII list has no Roman Numeral in 5000
{
int k1, n1;
string x1, x2, x3;
cout << "Number Conversion among Arabic,English and Roman" << endl;
cout << "(Roman numeral < 4000. English and Arabic < 1 million)" << endl;
cout << "Type 1: Arabic to English (with Roman if Arabic < 4000)" << endl;
cout << "Type 2: English to Arabic (with Roman if Arabic < 4000)" << endl;
cout << "Type 3: Roman to Arabic and English (Rom < 4000)" << endl;
cout << "Type -1: To quit this program" << endl;
while (x1 != "-1")
{
cout << "Type a number now: ";
getline(cin,x1);
if (x1 == "-1") break;
if (x1 == "1")
{
cout << "Enter a number in Arabic: ";
cin >> n1;
x2 = AraToEng(n1);
if (n1 < 4000) x3 = " and " + AraToRom(n1);
cout << n1 << " is: " << x2 << x3 << endl;
}
else if (x1 == "2")
{
cout << "Enter a number in English. e.g. 1925 is: " <<
"Nineteen Hundred And Twenty Nine" << endl;
getline(cin,x2);
n1 = EngToAra(x2);
if (n1 < 4000) x3 = " and " + AraToRom(n1);
cout << x2 << " is: " << n1 << x3 << endl;
}
else if (x1 == "3")
{
cout << "Enter a number in Roman (num < 4000) ";
cin >> x2;
n1 = RomToAra(x2);
x3 = AraToEng(n1);
cout << x2 << " is: " << n1 << " and " << x3 << endl;
}
}
}
string AraToEng(int pAra)
{
int k1;
string x1;
ifstream InFile("EngNum1b.txt", ios::in);
for (k1 = 1; k1 <= pAra; k1++)
getline(InFile,x1);
InFile.close();
return x1;
}
string AraToRom(int pAra)
{
int k1;
string x1;
ifstream InFile("Rnum3999.txt", ios::in);
for (k1 = 1; k1 <= pAra; k1++)
getline(InFile,x1);
InFile.close();
return x1;
}
int EngToAra(string pEng)
{
int k1,k2,n1,n2, aLen[] = {2,1,5,1,2}, bLen;
string x1,aWord[] = {", ", "-", " And "," ", " "},bWord;
// Remove formating characters.
for (k2 = 0; k2 <= 4; k2++)
{
n2 = -1;
bWord = aWord[k2]; bLen = aLen[k2];
for (k1 = 1; k1 <= 7; k1++)
{
n1 = n2 + 1;
n2 = pEng.find(bWord,n1);
if (n2 == -1) break;
pEng.erase(n2,bLen);
}
}
ifstream InFile("EngNum1a.txt", ios::in);
for (k2 = 1; k2 <= 999999; k2++)
{
InFile >> x1;
if (x1 == pEng) break;
}
InFile.close();
return k2;
}
int RomToAra(string pRom)
{
int k1;
string x1;
ifstream InFile("Rnum3999.txt", ios::in);
for (k1 = 1; k1 <= 3999; k1++)
{
InFile >> x1;
if (x1 == pRom) break;
}
InFile.close();
return k1;
}