Created
December 23, 2018 11:24
-
-
Save AmaranthLIS/49b0ef71327ba57ccd92b2fca5ff31d2 to your computer and use it in GitHub Desktop.
Calculate pressure on select row/position in Pyramid
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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