The challenge
You have to build a pyramid.
This pyramid should be built from characters from a given string.
You have to create the code for these four methods:
public static String watchPyramidFromTheSide(String characters)
public static String watchPyramidFromAbove(String characters)
public static int countVisibleCharactersOfThePyramid(String characters)
public static int countAllCharactersOfThePyramid(String characters)
The first method (“FromTheSide”) shows the pyramid as you would see from the side.
The second method (“FromAbove”) shows the pyramid as you would see from above.
The third method (“CountVisibleCharacters”) should return the count of all characters, that are visible from outside the pyramid.
The forth method (“CountAllCharacters”) should count all characters of the pyramid. Consider that the pyramid is completely solid and has no holes or rooms in it.
Every character will be used for building one layer of the pyramid. So the length of the given string will be the height of the pyramid. Every layer will be built with stones from the given character. There is no limit of stones.
The pyramid should have perfect angles of 45 degrees.
Example: Given string: “abc”
Pyramid from the side:
c
bbb
aaaaa
Pyramid from above:
aaaaa
abbba
abcba
abbba
aaaaa
Count of visible stones/characters:
25
Count of all used stones/characters:
35
There is no meaning in the order or the choice of the characters. It should work the same for example “aaaaa” or “54321”.
Hint: Your output for the side must always be a rectangle! So spaces at the end of a line must not be deleted or trimmed!
If the string is null or empty, you should exactly return this value for the watch-methods and -1 for the count-methods.
The solution in Java code
import static java.util.stream.Collectors.joining;
import java.util.Collections;
import java.util.function.IntFunction;
import java.util.stream.IntStream;
public class Pyramid {
public static String watchPyramidFromTheSide(final String characters) {
if (isInvalid(characters)) return characters;
return IntStream.rangeClosed(1, characters.length())
.mapToObj(palindrome(characters, repeat(" ", characters.length()))).collect(joining("\n"));
}
public static String watchPyramidFromAbove(final String characters) {
if (isInvalid(characters)) return characters;
return IntStream.concat(
IntStream.range(0, characters.length() - 1).map(i -> characters.length() - i),
IntStream.rangeClosed(1, characters.length())
).mapToObj(palindrome(characters, characters)).collect(joining("\n"));
}
public static int countVisibleCharactersOfThePyramid(final String characters) {
if (isInvalid(characters)) return -1;
final int b = 2 * characters.length() - 1;
return b * b;
}
public static int countAllCharactersOfThePyramid(final String characters) {
if (isInvalid(characters)) return -1;
return IntStream.rangeClosed(1, 2 * characters.length() - 1).filter(i -> i % 2 != 0).map(x -> x * x).sum();
}
private static final boolean isInvalid(final String s) {
return s == null || s.length() == 0;
}
private static final String repeat(final String s, final int n) {
return String.join("", Collections.nCopies(n, s));
}
private static final IntFunction<String> palindrome(final String characters, final String padCharacters) {
return i -> {
final int offset = characters.length() - i;
final int n = 2 * i - 1;
final String prefix = padCharacters.substring(0, offset);
final String center = repeat(String.valueOf(characters.charAt(offset)), n);
final String suffix = new StringBuilder(prefix).reverse().toString();
return prefix + center + suffix;
};
}
}
Test cases to validate our Java solution
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;
public class SolutionTest {
@Test
public void basicTest2() {
String characters = "*#";
String expectedWatchFromSide =
" # \n" +
"***";
String expectedWatchFromAbove =
"***\n" +
"*#*\n" +
"***";
String actualWatchFromSide = Pyramid.watchPyramidFromTheSide(characters);
String actualWatchFromAbove = Pyramid.watchPyramidFromAbove(characters);
visualisation(expectedWatchFromSide, expectedWatchFromAbove, actualWatchFromSide, actualWatchFromAbove);
assertEquals(9, Pyramid.countVisibleCharactersOfThePyramid(characters));
assertEquals(10, Pyramid.countAllCharactersOfThePyramid(characters));
}
@Test
public void basicTest3() {
String characters = "abc";
String expectedWatchFromSide =
" c \n" +
" bbb \n" +
"aaaaa";
String expectedWatchFromAbove =
"aaaaa\n" +
"abbba\n" +
"abcba\n" +
"abbba\n" +
"aaaaa";
String actualWatchFromSide = Pyramid.watchPyramidFromTheSide(characters);
String actualWatchFromAbove = Pyramid.watchPyramidFromAbove(characters);
visualisation(expectedWatchFromSide, expectedWatchFromAbove, actualWatchFromSide, actualWatchFromAbove);
assertEquals(25, Pyramid.countVisibleCharactersOfThePyramid(characters));
assertEquals(35, Pyramid.countAllCharactersOfThePyramid(characters));
}
private void visualisation(String expectedWatchFromSide, String expectedWatchFromAbove, String actualWatchFromSide, String actualWatchFromAbove) {
System.out.println("From side correct:\n" + expectedWatchFromSide);
System.out.println("From above correct:\n" + expectedWatchFromAbove);
System.out.println("From side yours:\n" + actualWatchFromSide);
System.out.println("From above yours:\n" + actualWatchFromAbove);
assertEquals(expectedWatchFromSide, actualWatchFromSide);
assertEquals(expectedWatchFromAbove, actualWatchFromAbove);
}
}