164 lines
4.9 KiB
C++
164 lines
4.9 KiB
C++
/*
|
||
Triangle, square, pentagonal, hexagonal, heptagonal, and octagonal numbers are all figurate (polygonal) numbers and are generated by the following formulae:
|
||
|
||
Triangle P3,n=n(n+1)/2 1, 3, 6, 10, 15, ...
|
||
Square P4,n=n2 1, 4, 9, 16, 25, ...
|
||
Pentagonal P5,n=n(3n−1)/2 1, 5, 12, 22, 35, ...
|
||
Hexagonal P6,n=n(2n−1) 1, 6, 15, 28, 45, ...
|
||
Heptagonal P7,n=n(5n−3)/2 1, 7, 18, 34, 55, ...
|
||
Octagonal P8,n=n(3n−2) 1, 8, 21, 40, 65, ...
|
||
The ordered set of three 4-digit numbers: 8128, 2882, 8281, has three interesting properties.
|
||
|
||
The set is cyclic, in that the last two digits of each number is the first two digits of the next number (including the last number with the first).
|
||
Each polygonal type: triangle (P3,127=8128), square (P4,91=8281), and pentagonal (P5,44=2882), is represented by a different number in the set.
|
||
This is the only set of 4-digit numbers with this property.
|
||
Find the sum of the only ordered set of six cyclic 4-digit numbers for which each polygonal type: triangle, square, pentagonal, hexagonal, heptagonal, and octagonal, is represented by a different number in the set.
|
||
*/
|
||
|
||
#include <bits/stdc++.h>
|
||
|
||
using namespace std;
|
||
|
||
uint triangle(uint n){
|
||
return n * (n + 1) / 2;
|
||
}
|
||
|
||
uint square(uint n){
|
||
return n * n;
|
||
}
|
||
|
||
uint pentagonal(uint n){
|
||
return n * (3 * n - 1) / 2;
|
||
}
|
||
|
||
uint hexagonal(uint n){
|
||
return n * (2 * n - 1);
|
||
}
|
||
|
||
uint heptagonal(uint n){
|
||
return n * (5 * n - 3) / 2;
|
||
}
|
||
|
||
uint octogonal(uint n){
|
||
return n * (3 * n - 2);
|
||
}
|
||
|
||
bool validEnd(uint n){
|
||
return n % 100 >= 10;
|
||
}
|
||
|
||
bool matchingCycle(int a, int b){
|
||
return (a % 100) == (b / 100);
|
||
}
|
||
|
||
const unsigned int Limit = 10000;
|
||
vector<unsigned int> all(Limit, 0);
|
||
uint finalMask = 0b111111000;
|
||
|
||
void fillVector(vector<uint> & toFill, const uint bitmask, uint (*calc)(uint n)){
|
||
uint value = calc(0);
|
||
|
||
for(uint i = 0; value < 10000; ++i){
|
||
if(value >= 1000 && validEnd(value)){
|
||
toFill[value] |= bitmask & finalMask;
|
||
}
|
||
value = calc(i + 1);
|
||
}
|
||
}
|
||
|
||
void search(uint& currentMask, vector<int>& results){
|
||
int backPart = results.back() % 100;
|
||
bool gottem = false;
|
||
|
||
for(int i = backPart * 100; i < backPart * 100 + 100; ++i){
|
||
if(all[i] && (currentMask | all[i]) != currentMask){
|
||
auto leftOvers = bitset<9>(~currentMask & all[i]);
|
||
int maskCopy = currentMask;
|
||
vector<int> resultsCopy(results);
|
||
|
||
// cout << "Currently looking at base of these numbers: ";
|
||
// for(auto x : results){
|
||
// cout << x << " ";
|
||
// } cout << '\n';
|
||
|
||
for(int j = 3; j < 9; ++j){
|
||
if(leftOvers[j]){
|
||
currentMask |= 1 << j;
|
||
results.push_back(i);
|
||
search(currentMask, results);
|
||
|
||
if(currentMask == finalMask && matchingCycle(results.back(), results.front())){
|
||
gottem = true;
|
||
break;
|
||
} else{
|
||
currentMask = maskCopy;
|
||
results = resultsCopy;
|
||
}
|
||
}
|
||
}
|
||
if(gottem){
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
int main(){
|
||
|
||
cout << "Hello this is Patrick" << endl;
|
||
auto start = chrono::high_resolution_clock::now();
|
||
|
||
// Finally learned what exactly it means when 1 << n, which is nice
|
||
fillVector(all, 1 << 3, triangle);
|
||
fillVector(all, 1 << 4, square);
|
||
fillVector(all, 1 << 5, pentagonal);
|
||
fillVector(all, 1 << 6, hexagonal);
|
||
fillVector(all, 1 << 7, heptagonal);
|
||
fillVector(all, 1 << 8, octogonal);
|
||
|
||
// for(uint i = 0; i < all.size(); ++i){
|
||
// if(all[i]){
|
||
// cout << i << " " << bitset<9>(all[i]) << endl;
|
||
// }
|
||
// }
|
||
|
||
bool gottem = false;
|
||
vector<int> results;
|
||
|
||
for(uint i = 0; i < all.size(); ++i){
|
||
if(all[i]){
|
||
// cout << "at " << i << '\n';
|
||
results.clear();
|
||
results.push_back(i);
|
||
|
||
auto bs = bitset<9>(all[i]);
|
||
for(uint j = 3; j < 9; ++j){
|
||
if(bs[j]){
|
||
uint mask = 1 << j;
|
||
search(mask, results);
|
||
if(mask == finalMask && matchingCycle(results.back(), results.front())){
|
||
gottem = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(gottem)
|
||
break;
|
||
}
|
||
}
|
||
|
||
int sum = 0;
|
||
for(auto r : results){
|
||
sum += r;
|
||
cout << r << " ";
|
||
} cout << endl;
|
||
cout << "Constituting to sum of: " << sum << endl;
|
||
|
||
auto duration = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start);
|
||
cout << (float)duration.count()/1000 << endl;
|
||
return 0;
|
||
} |