2016 CCC S4 Combining riceball code?? C++ - c++

the quesiton is like this :
Alphonse has N rice balls of various sizes in a row. He wants to form the largest rice ball possible for his friend to eat. Alphonse can perform the following operations:
If two adjacent rice balls have the same size, Alphonse can combine them to make a new rice ball. The new rice ball's size is the sum of the two old rice balls' sizes. It occupies the position in the row previously occupied by the two old rice balls.
If two rice balls have the same size, and there is exactly one rice ball between them, Alphonse can combine all three rice balls to make a new rice ball. (The middle rice ball does not need to have the same size as the other two.) The new rice ball's size is the sum of the three old rice balls' sizes. It occupies the position in the row previously occupied by the three old rice balls.
Alphonse can perform each operation as many times as he wants.
Determine the size of the largest rice ball in the row after performing 0 or more operations.
Input Specification
The first line will contain the integer, N (1≤N≤400).
The next line will contain N space separated integers representing the sizes of the riceballs, in order from left to right. Each integer is at least 1 and at most 1000000.
For 1 of the 15 available marks, N=4.
For an additional 2 of the 15 available marks, N≤10.
For an additional 2 of the 15 available marks, N≤50.
Output Specification
Output the size of the largest riceball Alphonse can form.
Sample Input 1
Copy
7
47 12 12 3 9 9 3
Output for Sample Input 1
Copy
48
Explanation for Sample Input 1
One possible set of moves to create a riceball of size 48 is to combine 12 and 12, forming a riceball of size 24. Then, combine 9 and 9 to form a riceball of size 18. Then, combine 3, 18 and 3 to form a riceball of size 24. Finally, combine the two riceballs of size 24 to form a riceball of size 48.
My code is this:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int num;
cin >> num;
vector<int> rice;
int temp;
for(int i = 0; i< num; i++)
{
cin >> temp;
rice.emplace_back(temp);
}
int change = 0;
int chain = 0;
for(int i = 0; i > -1; i++)
{
for(int j = 0; j < num; j++)
{
for(int k = 1; k < num-j; k++)
{
if(rice[j] == rice [j+k])
{
chain++;
}
else
{
k = num-j;
}
}
if(chain != 0)
{
for(int m = 1; m <= chain; m++)
{
rice[j] = rice[j] + rice[j+1];
rice.erase(rice.begin()+j+1, rice.begin()+j+2);
change = 1;
if(m == chain)
{
num -= chain;
change = 1;
chain = 0;
j=-1;
continue;
}
}
}
if(j < num-2)
{
if (rice[j] == rice[j+2])
{
rice[j] = rice[j] + rice[j+1] + rice[j+2];
rice.erase(rice.begin()+j+1, rice.begin()+j+3);
change = 1;
j=-1;
num-=2;
continue;
}
}
}
if(change == 0)
{break;}
change = 0;
}
sort(rice.begin(),rice.end());
cout << rice.back() << endl;
return 0;
}
the test case that doesn't work right now is input: 10 1 2 1 2 1 2 1 2 1 2 and the output should be 14, but the only way to get that is to ignore the 1 at the beginning which i got no idea how to do / thks a lot

Related

How can i get the sum of odd and even number with input user in Array C++

Our programming activity is to construct a C program that creates an array of size 12 and then display separately the sum of even-indexed cells and odd-indexed cells as well as their average. The sample run must be like this.
Sample Run:
Enter 12 elements: 1 1 1 1 1 1 1 1 1 1 1 1
Sum of even-indexed cells: 6
Sum of odd-indexed cells: 6
Average: 6.0
However, i'm having a trouble getting the sum of odd and even numbers. Like how i can make the program identify the odd and even placing in the array? Do i need to add "if-else" Here's my code.
#include <iostream>
using namespace std;
int A[11],B[11],C[11];
int sum,ave;
int x;
main()
{
cout<<"Enter 12 elements A: "<<endl;
for(x=0; x<11; x++)
cin>>A[x];
cout<<endl<<"Sum of even-indexed number: "<<endl;
for(x=0; x<=11; x++){
cout<<B[x];
}
cout<<endl<<"Sum of odd-indexed number: "<<endl;
for(x=0; x<=11; x++){
cout<<C[x];
}
cout<<endl<<"Average: "<<endl;
for(x=3; x<3; x++)
ave += B[x]+C[x]/A[x];
cout<<A[x]<<" ";
return 0;
}
You don't need 3 arrays. Just an array for the elements and 2 variables for the sums of evens and odds.
You could check the position in the array by checking if the remainder of the index divided by 2 equals 0.
You could also start an even position and increment the index by 2 so it would only check the even positions. For the odd positions you do the same, increment by 2 but start at an odd position.
#include <iostream>
using namespace std;
int main() {
int array[12];
int evenTotal = 0;
int oddTotal = 0;
for(int i=0;i<12;i++) {
cin>>array[i];
cout<<array[i]<<" ";
if(i%2 == 0){
//If we consider indexing with 0 to 11
// If we consider indexing with 1 to 12
// than this condition will be odd
evenTotal += array[i];
}
else {
oddTotal += array[i];
}
}
cout<<"\n";
// Because we have 6 evens and odds
int average = (evenTotal + oddTotal)/12;
cout<<"Even Total = "<<evenTotal<<"\n";
cout<<"Ödd Total = "<<oddTotal<<"\n";
cout<<"Average = "<<average;
return 0;
}
Check for output here : https://ideone.com/msYFh5

codechef: A puzzle game

problem statement:
Johnny has some difficulty memorizing the small prime numbers. So, his computer science teacher has asked him to play with the following puzzle game frequently.
The puzzle is a 3x3 board consisting of numbers from 1 to 9. The objective of the puzzle is to swap the tiles until the following final state is reached:
1 2 3
4 5 6
7 8 9
At each step, Johnny may swap two adjacent tiles if their sum is a prime number. Two tiles are considered adjacent if they have a common edge.
Help Johnny to find the shortest number of steps needed to reach the goal state.
My solution so far
#include<bits/stdc++.h>
using namespace std;
bool prime[20];
int matrix[3][3];
int solved[3][3] = {
{1,2,3},
{4,5,6},
{7,8,9}
};
void display()
{
for(int row = 0; row<3;row++)
{
for(int col = 0;col<3;col++)
{
cout<<matrix[row][col]<<" ";
}
cout<<endl;
}
cout<<endl<<endl;
}
bool check(){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(matrix[i][j]!=solved[i][j])
return false;
}
}
return true;
}
int min(int a,int b)
{
return (a<b)?a:b;
}
void generate(){
memset(prime,true,sizeof(prime));
for(int i=2;i*i<20;i++){
if(prime[i]==true)
{
for(int j=2*i;j<20;j+=i)
prime[j]=false;
}
}
}
int getMoves(int row, int col){
if(row < 0 ||col< 0 || row>=3||col>=3){
return 0;
}
if(check()){
return 0;
}
int moves = 0;
for(int i = row-1 ; i<= row+1 ;i++)
{
for(int j = col -1 ; j<=col+1;j++)
{
if((i!=row-1&&j!=col-1)||(i!=row+1&&j!=col+1)||(i!=row+1&&j!=col-1)||(i!=row-1&&j!=col+1)){
if(prime[matrix[row][col]+matrix[i][j]]==true)
{
moves+=getMoves(i,j);
int temp;
temp = matrix[i][j];
matrix[i][j] = matrix[row][col];
matrix[row][col] = temp;
display();
}
}
}
}
return moves;
}
int Moves(){
int minMoves = INF;
for(int row = 0;row<3;row++)
{
for(int col = 0;col<3;col++)
{
int moves = getMoves(row,col);
minMoves = min(moves,minMoves);
}
}
return minMoves;
}
int main(){
generate();
int t;
cin>>t;
while(t--)
{
for(int row = 0; row<3;row++)
{
for(int col = 0;col<3;col++)
{
cin>>matrix[row][col];
}
}
}
cout<<Moves();
}
sample testcase
Input:
2
7 3 2
4 1 5
6 8 9
9 8 5
2 4 1
3 7 6
Output:
6
-1
the program keeps crashing I guess because of memory overflow issue.
if (row < 0 || col< 0 || row >= 3 || row <= 3) {
return 0;
}
The code after this part is 'not accessible' because this condition is always true (... row >= 3 || row <= 3). You probably meant to write: (... row >= 3 || col >= 3)
I'm afraid your code is completely wrong and I don't think it could by fixed without complete rewrite. For example in function getMoves() your variables i and j can acquire value -1 so you will face access violation error. Secondly you have a recursion there, but you don't change data before you invoke recursion. Let's assume you want to swap 7 and 4. In the next step (because you didn't change input) you can swap 4 and 1. But it's not a correct move, because in that time, 4 should't be there. Thirdly your function getMoves() can end in an endless loop.
In conclusion, these kinds of problem are solved quite differently. You can for exmaple use backtracking algorithm or you can use A* algorithm. You will have to evaluate your current state. Let assume the following state:
7 3 2
4 5 6
1 8 9
You can measure number of moves that the number has to do to go to its correct position. So in this case 1 has to do 2 moves, 7 has to do 2 moves, 2 has to do 1 move as well as the number 3. The value of this state is 2 + 2 + 1 + 1 = 6. It's called an heuristic function. Now you can take this function and put it in an A* algorithm, and you should see the correct result.

Plotting Coordinates from a .txt File

I am finishing the second half of a two-part assignment on Conway's Game of Life. I created a function to generate a random array of 1s and 0s; the 1s represent a living cell and the zero an empty space. I created a separate function to inspect the neighborhood and make a count to determine how the game progresses. The rules: if a cell has 2 or 3 neighbors it survives, more than 3 or less than 2 it dies, and if an empty space has 3 neighbors it is "born". I even got help from you guys to wrap the screen using the modulus, but I am having trouble importing a .txt file to finish part two. Here is the code for part one:
#include <iostream> //includes input-output stream
#include <time.h> //includes time function
#include <iomanip> //includes setprecision function
#include <unistd.h> //includes sleep function
#include <fstream> //includes ifstream function
using namespace std; //using standard library
int master[24][79]; //initializes primary data array
int h = 24; // initializes height variable
int w = 79; // initialises width variable
int noOfCycles; //initialize cycles variable
void gen0 (int master[24][79]); // creates initial generation
void life(int master[24][79]); //initializes life function
void copy(int arrayX[24][79], int arrayY[24][79]); //initializes cycle update function
void print(int master[24][79]); //initializes print function
void fillPercent (int master[24][79]); //initializes percentage calculating function
int main() //initialize main function
{
cout << "How many cycles would you like to run?"; //prompt user to input cycles
cin >> noOfCycles; //user inputs cycles
srand (time(0)); //creates initial randomness
gen0(master); //creates initial generation
for (int k = 0; k <= noOfCycles; k++) //prints gen0 and cycles 50 times
{
print(master); //prints current array
fillPercent(master); //calculates/prints fill percentage
cout << " Cycle #" << k << " Author: Mikhail Morgan" << endl << endl;
//prints cycle number and signature
life(master); //calls life function
sleep(1); //delays output by 1 second
} //end width loop
} //end main function
void gen0 (int master[24][79])
{
for(int j = 0; j < h; j++) //height loop
{
for (int i = 0; i < w; i++) //width loop
master[j][i] = rand() % 2; //creates random generation 0
} //end height loop
}
void print(int master[24][79]) //Prints array
{
for(int j = 0; j < h; j++) //height loop
{
for(int i = 0; i < w; i++) //width loop
{
if(master[j][i] == 1)
cout << '0'; //print living cells as zeros
else
cout << ' '; //print dead cells as spaces
} // end width loop
cout << endl;
} // end height loop
} //end print function
void fillPercent (int master[24][79]) // calculates fill percentage
{
double fillNumber = 0; //resets every cycle
for (int i = 0; i < h; i++ ) //width loop
{
for (int j = 0; j < w; j++ ) //height loop
{
fillNumber += master[i][j]; //increments fill number
} //end height loop
} //end width loop
cout << endl << fixed << setprecision(2) << (fillNumber/(w*h))*100; //print percentage
} //end fillPercent function
void life (int master[24][79]) //generates/kills cells based on neighborhood
{
int temp[24][79]; //temporary array for manipulating data
copy (master, temp); //copy array onto temp
for(int j = 0; j < h; j++) //height loop
{
for (int i = 0; i < w; i++) //width loop
{
int count = 0; //intialize neighbor count variable
count = master[(j-1+h) % h][i % w] + //searches down
master[(j-1+h) % h][(i-1+w) % w] + //down left
master[j % h][(i-1+w) % w] + //left
master[(j+1+h) % h][(i-1+w) % w] + //up left
master[(j+1+h) % h][i % w] + //up
master[(j+1+h) % h][(i+1+w) % w] + //up right
master[j % h][(i+1+w) % w] + //right
master[(j-1+h) % h][(i+1+w) % w]; //down right
//cell dies if count falls below 2 or rises above 3
if(count < 2 || count > 3)
temp[j][i] = 0;
//cell stays alive if it has two neighbors
if(count == 2)
temp[j][i] = master[j][i];
//cell either stays alive or gets born if three neighbors
if(count == 3)
temp[j][i] = 1;
} //end width loop
}//end height loop
copy(temp, master); //copy temp back to main array
} //end life function
void copy(int arrayX[24][79], int arrayY[24][79]) //Copy machine
{
for(int j = 0; j < h; j++) //height loop
{
for(int i = 0; i < w; i++) //width loop
arrayY[j][i] = arrayX[j][i]; //temporary arrays used for copying
} //end height loop
} //end copy function
I know, using namespace std is lame af but it's mandated by my dinosaur-of-a-professor.
My problem is that for part two he wants us to stream the coordinates for the initial generation from a file that he supplied called GliderGun.txt. I am using Xcode and Im 99% sure that I have the file in the right location: I can see it in the right hand menu inside the same folder as main.cpp, and I can see the original copy in the Finder menu next to main.cpp. The first line is not a coordinate pair, it is the total number of coordinates in the file... Im not sure what the purpose of that is, and I suspect its whats messing me up. Here is the text from the file itself:
36
1 25
2 23
2 25
3 13
3 14
3 21
3 22
3 35
3 36
4 12
4 16
4 21
4 22
4 35
4 36
5 1
5 2
5 11
5 17
5 21
5 22
6 1
6 2
6 11
6 15
6 17
6 18
6 23
6 25
7 11
7 17
7 25
8 12
8 16
9 13
9 14
Here is the code for the function that replaces gen0. All I did was replace the call for gen0 with getPattern and altered the definition to look like this:
void getPattern (int master[24][79]) //generates Glider Gun
{
ifstream infile("GliderGun.txt", ios::in);
infile.open("GliderGun.txt", ios::in);//opens .txt file
int numOfCoordinates; // number of coordinate pairs
int i, j; // x, y coordinates
infile >> numOfCoordinates;
for (int a = 0; a < numOfCoordinates; a++)
{
infile >> i >> j;
master[j][i] = 1;
}
infile.close(); // closes .txt file
}
The console produces a blank 24x79 array. I sense that I have a looping problem but I dont know enough about how ifstream works to fix it. The coordinates are listed as (x y) or as defined by my other loops, (j i). I don't need the console to print the file I just need it to write 1s in the coordinates that are listed. Thanks for any advice!
Just from trying to reason about your code, there are two problems that arise from a drop-in replacement of getPattern where gen0 used to be:
You don't initialize any of the slots of your array to zero.
You're reading in the number of lines as an x-coordinate for one of the cells, all of the x-coordinates as y-coordinates, most of the y-coordinates as x-coordinates, and not reading the last y-coordinate.
There are two simple enough changes you can make to fix this.
Before reading from the file set the value in all cells of your 2D-array to 0.
Even if you're not doing anything with it, read in the number of lines from the file before looping over the coordinates.
Unrelated to your code, the text file does not need to be in the same directory as the source file, it needs to be in the same directory that the program is executed from. I don't know where the execution will be done from in XCode, but it might be worth testing directly from your computer's shell, if you know how.
Edit:
The part of getPattern where you read from the file could look something like this:
int num_coordinates; // This will be the number of coordinate pairs your file says it has.
int i, j; // These will be your x, y coordinates.
infile >> num_coordinates;
for (int loop_ct = 0; loop_ct < num_coordinates; loop_ct++) {
infile >> i >> j;
master[j][i] = 1;
}

Algorithm for Combinations of given numbers with repetition? C++

So I N - numbers I have to input, and I got M - numbers of places for those numbers and I need to find all combinations with repetition of given numbers.
Here is example:
Let's say that N is 3(I Have to input 3 numbers), and M is 4.
For example let's input numbers: 6 11 and 533.
This should be result
6,6,6,6
6,6,6,11
6,6,6,533
6,6,11,6
...
533,533,533,533
I know how to do that manualy when I know how much is N and M:
In example where N is 3 and M is 4:
int main()
{
int N = 3;
int M = 4;
int *numbers = new int[N + 1];
for (int i = 0; i < N; i++)
cin >> numbers[i];
for (int a = 0; a < N; a++)
for (int b = 0; b < N; b++)
for (int c = 0; c < N; c++)
for (int d = 0; d < N; d++)
{
cout << numbers[a] << " " << numbers[b] << " " << numbers[c] << " " << numbers[d] << endl;
}
return 0;
}
But how can I make algorithm so I can enter N and M via std::cin and I get correct resut?
Thanks.
First one short tip: don't use "new" or C-style arrays in C++ when we have RAII and much faster data structures.
For the solution to your problem I would suggest making separate function with recursion. You said you know how to do it manually so the first step in making it into algorithm is to tear down you manual solution step by step. For this problem when you solve it by hand you basically start with array of all first numbers and then for last position you just loop through available numbers. Then you go to the second last position and again loop through available numbers just now with the difference that for every number there you must also repeat the last spot number loop. Here is the recursion. For every "n"th position you must loop through available numbers and for every call the same function for "n+1"th number.
Here is a simplified solution, leaving out the input handling and exact print to keep code shorter and more focused on the problem:
#include <vector>
#include <iostream>
void printCombinations(const std::vector<int>& numbers, unsigned size, std::vector<int>& line) {
for (unsigned i = 0; i < numbers.size(); i++) {
line.push_back(numbers[i]);
if (size <= 1) { // Condition that prevents infinite loop in recursion
for (const auto& j : line)
std::cout << j << ","; // Simplified print to keep code shorter
std::cout << std::endl;
line.erase(line.end() - 1);
} else {
printCombinations(numbers, size - 1, line); // Recursion happens here
line.erase(line.end() - 1);
}
}
}
int main() {
std::vector<int> numbers = {6, 11, 533};
unsigned size = 4;
std::vector<int> line;
printCombinations(numbers, size, line);
return 0;
}
If you have any questions feel free to ask.
Totally there is no need for recursion here. This is a typical job for dynamic programming. Just get the first solution right for n = 1 (1 slot is available) which means the answer is [[6],[11],[533]] and then move on one by one by relying on the one previously memoized solution.
Sorry that i am not fluent in C, yet in JS this is the solution. I hope it helps.
function combosOfN(a,n){
var res = {};
for(var i = 1; i <= n; i++) res[i] = res[i-1] ? res[i-1].reduce((r,e) => r.concat(a.map(n => e.concat(n))),[])
: a.map(e => [e]);
return res[n];
}
var arr = [6,11,533],
n = 4;
console.log(JSON.stringify(combosOfN(arr,n)));
Normally the easiest way to do dynamic nested for loops is to create your own stack and use recursion.
#include <iostream>
#include <vector>
void printCombinations(int sampleCount, const std::vector<int>& options, std::vector<int>& numbersToPrint) {
if (numbersToPrint.size() == sampleCount) {
// got all the numbers we need, print them.
for (int number : numbersToPrint) {
std::cout << number << " ";
}
std::cout << "\n";
}
else {
// Add a new number, iterate over all possibilities
numbersToPrint.push_back(0);
for (int number : options) {
numbersToPrint.back() = number;
printCombinations(sampleCount, options, numbersToPrint);
}
numbersToPrint.pop_back();
}
}
void printCombinations(int sampleCount, const std::vector<int>& options) {
std::vector<int> stack;
printCombinations(sampleCount, options, stack);
}
int main()
{
printCombinations(3, {1,2,3});
}
output
1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3
2 1 1
2 1 2
2 1 3
2 2 1
2 2 2
2 2 3
2 3 1
2 3 2
2 3 3
3 1 1
3 1 2
3 1 3
3 2 1
3 2 2
3 2 3
3 3 1
3 3 2
3 3 3
Here is an algorithm to solve this, that does't use recursion.
Let's say n=2 and m=3. Consider the following sequence that corresponds to these values:
000
001
010
011
100
101
110
111
The meaning of this is that when you see a 0 you take the first number, and when you see a 1 you take the second number. So given the input numbers [5, 7], then 000 = 555, 001=557, 010=575 etc.
The sequence above looks identical to representing numbers from 0 to 7 in base 2. Basically, if you go from 0 to 7 and represent the numbers in base 2, you have the sequence above.
If you take n=3, m=4 then you need to work in base 3:
0000
0001
0002
0010
0011
0012
....
So you go over all the numbers from 0 to 63 (4^3-1), represent them in base 3 and follow the coding: 0 = first number, 1 = second number, 2 = third number and 3 = fourth number.
For the general case, you go from 0 to M^N-1, represent each number in base N, and apply the coding 0 = first number, etc.
Here is some sample code:
#include <stdio.h>
#include <math.h>
void convert_to_base(int number, char result[], int base, int number_of_digits) {
for (int i = number_of_digits - 1; i >= 0; i--) {
int remainder = number % base;
number = number / base;
result[i] = '0' + remainder;
}
}
int main() {
int n = 2, m = 3;
int num = pow(n, m) - 1;
for (int i = 0; i <= num; i++) {
char str[33];
convert_to_base(i, str, n, m);
printf("%s\n", str);
}
return 0;
}
Output:
000
001
010
011
100
101
110
111

Stuck with spiral triangle

I am looking for an algorithm that numbers and outputs a triangle with sides n (or half of a square) where n is an input of the program. But the numbering starts at the top of the triangle, goes down the diagonal, back along the bottom row and up the left edge. If there is an interior remaining it goes diagonally down from the highest number and continues.
Here is an example:
1
9 2
8 10 3
7 6 5 4
Here is my code and it results in:
1
10 2
9 8 3
7 6 5 4
Is there any algorithm for this of program if there any please explain to me.
The above program works well with row size less than 3 but doesn't for size above 3.
#include<iostream.h>
#include<conio.h>
void main()
{
int n,i,j,v=0;
static int k;
clrscr();
cout<<"Enter the number of rows : ";
cin>>n;
for(i=0;i<n;i++)
{
for(j=0;j<=i;j++)
{
v++;
}
}
for(i=0;i<n;i++)
{
for(j=0;j<i;j++)
{
cout<<v;
cout<<"\t";
v--;
}
while(k==i)
{
k++;
cout<<k;
cout<<"\t";
}
cout<<"\n";
}
getch();
}
Here's a solution that doesn't use any array storage. The spiral can be thought of as a set of right angled triangles inside each other. The function iterates over all the rows and columns and for each position, it calculates what triangle the element is on by finding the closest distance to the edge of the outer triangle, then computes its adjusted position (x, y) relative to the top-left corner of that inner triangle, the number of rows of the inner triangle (r), and the start number of the inner triangle (start+1). Then it outputs a number based on whether it lies on the diagonal, horizontal or vertical side.
#include <iostream>
#include <iomanip>
using namespace std;
int main(void) {
int rows;
cout << "Enter the number of rows : ";
cin >> rows;
int i, j;
for(i = 0; i < rows; i++)
{
for(j = 0; j <= i; j++)
{
// find the closest side:
int distance = j; // distance to vertical side
if(i-j < distance)
distance = i-j; // distance to diagonal side
if((rows-1)-i < distance)
distance = (rows-1)-i; // distance to horizontal side
int r = rows - distance * 3;
// compute position on inner triangle:
int x = j - distance;
int y = i - distance * 2;
// compute start number for inner triangle:
int start = (((rows+1)*rows)/2) - (((r+1)*r)/2);
// output number based on side:
if(x==y) // diagonal side
cout << setw(2) << (start+y+1) << " ";
else if(y==(r-1)) // horizontal side
cout << setw(2) << (start+(r*2)-(x+1)) << " ";
else // vertical side
cout << setw(2) << (start+(r*3)-(y+2)) << " ";
}
cout << endl;
}
return 0;
}
Demo
Take the example where rows equals 7. In that case the distance value for each element will be:
(0)
0 0
0 (1) 0
0 1 1 0
0 1 (2) 1 0
0 1 1 1 1 0
0 0 0 0 0 0 0
All elements with the same distance value form a triangle. The number of rows of the outer triangle is 7, the next smaller one has 4, then 1. So r = rows - (distance * 3).
The top-left corner of the outer triangle is at row 0, column 0. The first inner triangle is row 2, column 1, the next one is at row 4, column 2. So the position of a given row/column position on the inner triangle that it lies on is found by subtracting distance * 2 from the row and distance from the column, so y = i - (distance *2) and x = j - distance.
The inner triangle column is stored in x. The inner triangle row is stored in y. In the example above, the values in brackets are the top-left corners of each triangle, where x = 0 and y = 0. For example for the top-left corner of the triangle with distance = 1, i = 2 and j = 1, so x = 1 - 1 = 0, and y = 2 - (1 * 2) = 0.
The start value is found by calculating the number of elements in the entire large triangle ((row+1)*row)/2 and then subtracting the number of elements remaining, which is the number of elements in the inner triangle.
For a triangle with n rows, the total number of elements is ((n+1)*n)/2, as shown below for rows = 5:
1 X 0 0 0 0 0
2 X X 0 0 0 0
3 X X X 0 0 0
4 X X X X 0 0
5 X X X X X 0
1 2 3 4 5 6
To count the number of X's, we can see that it's half the number of elements in a rectangle of (5+1)*5, so half of 30, which is 15.
If there are 2 triangles one inside the other, like this:
X
X X
X O X
X O O X
X X X X X
and we want to count the number of X's, then we can calculate the size of the entire triangle using the above formula to get 15, and then calculate the size of the inner triangle which has 2 rows as ((2+1)*2)/2 = 3, and subtracting the smaller from the larger gives 15 - 3 = 12. So if there are 12 X's, then the first O must be number 13. That's how we can calculate the number to output for the top-left corner of the inner triangle.
Once you've calculated all that it's just a matter of working out which side of the inner triangle the element is on and printing it out.
Here is a general idea as to how to solve this with recursion. There is probably a way to solve this in a space-efficient way, but I leave that for someone else. So let's say we store this as an array of arrays accessed by x[i][j] and let's say the size of sides of the triangle are n. You can google for how to dynamically create an array of arrays.
Now what we want is an equation for the outside of the triangle. Numbers along the diagonal are (i(i+1))/2 for 1 <= i <= n. Numbers along the left edge are 1+(i(i-1))/2 for 1 <= i <= n. And numbers along the bottom are 1+(n(n-1))/2 .. (n(n+1))/2.
So now to the recursion. Let j be the size of the remaining triangle yet to be numbered, k the highest number you've encountered before and (l,m) the index of the top of the triangle. Use the equations above and the preceding information to calculate the number and store that into the remaining triangle array. If there is yet another interior, recurse with the highest number and index of the top. And so on.
Example for side size 4. First number the outside. Highest prior number is 0. Index of the first position is (0,0)
1
9 2
8 x 3
7 6 5 4
We are not done because we still have an interior of size one. So when you recurse you, the position of the top of the triangle is (2,2), the highest number so far is 9 and the size of the triangle remaining is 1.
Now try with side size 5. After the first numbering we'd get:
1
12 2
11 x 3
10 x x 4
9 8 7 6 5
And the triangle remaining also starts at (2,2) as for side 4. But the size of the triangle remaining is now 2 and the highest number seen so far is 12.
After all the recursion is done, then print out of the table.
Easy way is to use an array.
#include <iostream>
using namespace std;
int main(){
int n;
cout <<"Enter the number of rows : ";
cin >> n;
int **tri = new int *[n];
for(int i=0; i<n; i++){
tri[i] = new int[i+1];
}
int v = 0, r = 0, c = 0;
for(int k = n-1; 0 <= k; k -=3){//k is total side size / 3, next k -2 -1
if(k==0){
tri[r][c] = ++v;
break;
}
for(int i = 0; i < k; ++i)//↘
tri[r++][c++] = ++v;
for(int i = 0; i < k; ++i)//←
tri[r][c--] = ++v;
for(int i = 0; i < k; ++i)//↑
tri[r--][c] = ++v;
r += 2; ++c;//next start position
}
//print
for(r = 0; r < n; ++r){
for(c = 0; c <= r; ++c)
cout << tri[r][c] << '\t';
cout << endl;
}
for(int i=0; i<n; i++){
delete[] tri[i];
}
delete[] tri;
}