Reputation: 65
I need to print an array of characters in a pyramid shape. What I have so far is this:
char[] chars = {'F', 'E', 'L', 'I', 'Z', ' ', 'A', 'N','I', 'V', 'E', 'R', 'S', 'A', 'R', 'I', 'O'};
int length = chars.length;
for (int i = 1; i < length; i += 2) {
for (int j = 0; j < 9 - i / 2; j++)
System.out.print(" ");
for (int j = 0; j < i; j++)
System.out.print(chars[j]);
System.out.print("\n");
}
for (int i = length; i > 0; i -= 2) {
for (int j = 0; j < 9 - i / 2; j++)
System.out.print(" ");
for (int j = 0; j < i; j++)
System.out.print(chars[j]);
System.out.print("\n");
and it prints this:
F
FEL
FELIZ
FELIZ A
FELIZ ANI
FELIZ ANIVE
FELIZ ANIVERS
FELIZ ANIVERSAR
FELIZ ANIVERSARIO
FELIZ ANIVERSAR
FELIZ ANIVERS
FELIZ ANIVE
FELIZ ANI
FELIZ A
FELIZ
FEL
F
But I need it to start printing from the character in the middle of the array. The end result gotta be like this:
I
NIV
ANIVE
ANIVER
Z ANIVERS
IZ ANIVERSA
LIZ ANIVERSAR
ELIZ ANIVERSARI
FELIZ ANIVERSARIO
ELIZ ANIVERSARI
LIZ ANIVERSAR
IZ ANIVERSA
Z ANIVERS
ANIVER
ANIVE
NIV
I
Any help would be greatly appreciated.
Upvotes: 5
Views: 1331
Reputation: 2044
You can do the same thing as show on below code. It will use lesser number of for loops. I have added inline comments in the code go through it.
char[] chars = { 'F', 'E', 'L', 'I', 'Z', ' ', 'A', 'N', 'I', 'V', 'E', 'R', 'S', 'A', 'R', 'I', 'O' };
int length = chars.length;
for (int line=0;line<=length;line++) {
//This will print upper part of pyramid
if(line < length/2){
String output="";
int middelVal=length/2;
for (int i = middelVal - line; i > 0; i--) {
output=output+" ";
}
for (int i = middelVal - line; i <= middelVal + line; i++) {
output=output+chars[i];
}
System.out.println(output);
}else if(line > length/2){
//This will print lower part of pyramid
String output="";
int middelVal=length/2;
int nwNum = chars.length-line;
for (int i = middelVal - nwNum; i > 0; i--) {
output=output+" ";
}
for (int i = middelVal - nwNum; i <= middelVal + nwNum; i++) {
output=output+chars[i];
}
System.out.println(output);
}
}
Upvotes: 5
Reputation: 871
Getting the middle index, storing it in two variables will mark where to start and end the character printing.
int mid = length / 2; // left end
int midLen = mid; // right end
The loop will start printing spaces until the left end mid
, then chars will be printed until the right end midLen + 1
. Then increment midLen
to go further right, and decrement mid
to go further left.
for(int i = mid; mid > -1; mid--, midLen++) {
for(int s = 0; s < mid; s++)
System.out.print(" ");
for (int j = mid; j < midLen + 1; j++) {
System.out.print(chars[j]);
}
System.out.print("\n");
}
To print the lower pyramid, we'll start from 0
index to length
. This time, we increment mid
to go further right, and decrement midLen
to go further left, truncating the string line per line until the middle character.
mid = 0;
midLen = length;
for(int i = mid; midLen != length / 2; mid++, midLen--) {
for(int s = 0; s < mid; s++)
System.out.print(" ");
for(int j = mid; j < midLen; j++) {
System.out.print(chars[j]);
}
System.out.print("\n");
}
BONUS: Harnessing Java 8's new features. Same mechanism, I'll leave the examining for you.
...
static int mid;
static int midLen;
static String line = "";
public static void main(String[] args) {
char[] chars = {'F', 'E', 'L', 'I', 'Z', ' ', 'A', 'N','I', 'V', 'E', 'R', 'S', 'A', 'R', 'I', 'O'};
mid = chars.length / 2;
midLen = mid;
List<String> tri = new ArrayList<String>();
IntStream.rangeClosed(0, mid)
.forEach(i -> {
Stream.of(chars).forEach( j -> {
IntStream.range(0, mid).forEach(x -> line += " ");
IntStream.rangeClosed(mid, midLen)
.forEach(x -> line += String.valueOf(chars[x]));
mid--;
midLen++;
tri.add(line);
line = "";
});
});
tri.forEach(System.out::println); // print upper pyramid
Collections.reverse(tri);
tri.forEach(System.out::println); // print lower pyramid
}
...
Upvotes: 3
Reputation: 3201
This is off the top of my head, but one method I'd try would be like this:
Find the index of my middle character in the array. Call this 'startIndex'
For every line, I would find the length, divide by 2 (round down) and this would be the starting offset from startIndex that determines what my first character would be.
Let's say I'm on line 5, which you have as "Z ANIVERS". That has a length of 9. Divide by 2 (and round down), you get 4.
In your chars array, the startIndex is calculated to be 8 (17 / 2, round down). Thus I should start printing from char 4 (which is startIndex - 4) in my char array up to however many characters needed.
You can also easily print the whole line without counting characters in a loop, since if you know the line length needed and the starting char index, you could just substring that line out in one go if you had your initial characters as one string.
Finally, you can also only do half the work since it looks like your top half is the same as the bottom half (build the result in strings then concatenate them together to print out the full result)
edit: Reading my answer over, you wouldn't need to actually 'find' the line length as it just starts from 1 and increases by 2 every time, but the original method would still be the same.
edit 2:
Since everyone is adding their coded version (and the answer has been accepted), I might as well add mine following what I said:
String sourceString = "FELIZ ANIVERSARIO"; // source of characters
String padding = " "; // used to create the padding offset for each line
int middle = sourceString.length() / 2;
// top and bottom halves of the output
String top = "";
String bottom = "";
for(int currentLength = 1; currentLength < sourceString.length(); currentLength += 2){
String linePadding = padding.substring(currentLength / 2, padding.length());
// speical case here, in the given example by the post, the 4th line the offset is one less as the I characters do not line up in the middle
// 7 is used as the 4th line has a length of 7
if(currentLength == 7){
linePadding = linePadding.substring(1, linePadding.length());
}
top += linePadding + sourceString.substring(middle - (currentLength / 2), middle + (currentLength / 2) + 1) +"\n";
bottom = linePadding + sourceString.substring(middle - (currentLength / 2), middle + (currentLength / 2) + 1) + "\n" + bottom;
}
System.out.println(top + sourceString +"\n"+ bottom);
Not sure if this was intentional, but I added a special expectation in the loop where I noticed in the user's example the 4th line is off by 1 (the I's don't line up there). If the I's are supposed to line up and it was a typo, can remove that if block entirely.
Upvotes: 2
Reputation: 12817
Here is another approach using 2d array
char[] chars = { 'F', 'E', 'L', 'I', 'Z', ' ', 'A', 'N', 'I', 'V', 'E', 'R', 'S', 'A', 'R', 'I', 'O' };
int size = chars.length;
int mid = size / 2 + 1;
char[][] matrix = new char[size][size];
for (char[] cs : matrix) {
Arrays.fill(cs, ' ');
}
for (int i = 0; i < size; i++) {
int l = Math.abs(mid - 1 - i);
int r = size - l;
for (int m = l; m < r; m++) {
matrix[i][m] = chars[m];
}
}
for (char[] cs : matrix) {
System.out.println(cs);
}
output
I
NIV
ANIVE
ANIVER
Z ANIVERS
IZ ANIVERSA
LIZ ANIVERSAR
ELIZ ANIVERSARI
FELIZ ANIVERSARIO
ELIZ ANIVERSARI
LIZ ANIVERSAR
IZ ANIVERSA
Z ANIVERS
ANIVER
ANIVE
NIV
I
Upvotes: 3