Skip to content

Instantly share code, notes, and snippets.

@AmaranthLIS
Created December 23, 2018 11:24
Show Gist options
  • Save AmaranthLIS/49b0ef71327ba57ccd92b2fca5ff31d2 to your computer and use it in GitHub Desktop.
Save AmaranthLIS/49b0ef71327ba57ccd92b2fca5ff31d2 to your computer and use it in GitHub Desktop.
Calculate pressure on select row/position in Pyramid
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Main {
public static void main(String... args) {
int row = 322, position = 156;
PyramidPressure pyramidPressure = new PyramidPressure();
BigDecimal value = pyramidPressure.getPressure(row, position);
System.out.println("Result = " + value);
}
}
class PyramidPressure {
private static final BigDecimal TWO = BigDecimal.valueOf(2);
public BigDecimal getPressure(int row, int position) throws IllegalArgumentException {
if (position > row) throw new IllegalArgumentException("Position is much more then a row");
BigDecimal[][] pyramid = calcPyramid(row + 1);
int half = getHalfLength(row);
if ((position + 1) > half) {
int part = row - position + 1;
part = half - part;
position = half - part - 1;
}
return pyramid[row][position].subtract(BigDecimal.ONE);
}
private BigDecimal[][] calcPyramid(int height) {
final BigDecimal weight = BigDecimal.ONE;
//todo improve this calculate, keep array to cache
BigDecimal[][] pyramid = new BigDecimal[height][height];
for (int i = 0; i < height; i++) {
if (isFirstElement(i)) {
pyramid[i][0] = weight;
continue;
}
int half = getHalfLength(i);
for (int j = 0; j <= i; j++) {
if (j < half) {
BigDecimal weightBlock1;
BigDecimal weightBlock2;
if (isFirstElement(j)) {
weightBlock1 = BigDecimal.ZERO;
weightBlock2 = divide(pyramid, i - 1, j);
} else if (isLastElement(i, j, half)) {
weightBlock1 = divide(pyramid, i - 1, j - 1);
weightBlock2 = weightBlock1;
} else {
weightBlock1 = divide(pyramid, i - 1, j - 1);
weightBlock2 = divide(pyramid, i - 1, j);
}
pyramid[i][j] = weight.add(weightBlock2.add(weightBlock1));
}
}
}
return pyramid;
}
private boolean isFirstElement(int n) {
return n == 0;
}
private boolean isLastElement(int i, int j, int half) {
return (i % 2) == 0 && j == (half - 1);
}
private BigDecimal divide(BigDecimal[][] pyramid, int i, int j) {
return pyramid[i][j].divide(TWO, 14, RoundingMode.HALF_EVEN).stripTrailingZeros();
}
private int getHalfLength(int i) {
int row = i + 1;
int half = (row / 2);
if ((row % 2) != 0) {
half = half + 1;
}
return half;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment