Last active
June 3, 2019 15:57
-
-
Save abdallaadelessa/2ac85a8ae14284c24d55a0c698412a7a to your computer and use it in GitHub Desktop.
This file contains hidden or 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.lang.StringBuilder | |
/** | |
* Pyramid generator | |
* | |
* Develop a function which generates a pyramid: | |
* | |
* fun pyramidGenerator(levels: Int): List<String> | |
* | |
* "levels" is a positive integer. | |
* The function returns a List<String> representing the pyramid shape with n levels. | |
* The stones are represented by "#" character | |
* The air is represented by a space character. | |
* Make sure the generated pyramid has spaces on both the left and right hand sides. | |
* | |
* | |
* pyramid(1) | |
* '#' | |
* | |
* pyramid(2) | |
* ' # ' | |
* '###' | |
* | |
* pyramid(3) | |
* ' # ' | |
* ' ### ' | |
* '#####' | |
*/ | |
fun main() { | |
pyramidGenerator(10).print() | |
} | |
fun pyramidGenerator(levels: Int) = | |
levels.run { 1.rangeTo(Math.abs(this)) } | |
.run { Pyramid(this, 1 until last * 2) { y -> y * 2 - 1 } } | |
.run { build() } | |
private fun List<String>.print() = forEach { System.out.println(it) } | |
//region Pyramid Logic | |
private const val STONE = "#" | |
private const val AIR = " " | |
private data class Pyramid( | |
private val yAxisRange: IntRange, | |
private val xAxisRange: IntRange, | |
private val numOfStonesPerRowFormula: (Int) -> Int | |
) { | |
private val yValueToAmountOfAirPerRowSideMap: MutableMap<Int, Int> = mutableMapOf() | |
private val xAxisPointsCount = xAxisRange.last | |
private fun calculateAmountOfAirPerRow(y: Int) = xAxisPointsCount - numOfStonesPerRowFormula(y) | |
private fun calculateAmountOfAirPerRowSide(y: Int): Int = calculateAmountOfAirPerRow(y) / 2 | |
private fun calculateOrGetTheAmountOfAirPerRowSide(y: Int) = | |
yValueToAmountOfAirPerRowSideMap[y] ?: calculateAmountOfAirPerRowSide(y).apply { | |
yValueToAmountOfAirPerRowSideMap[y] = this | |
} | |
private fun isAir(x: Int, y: Int) = x <= calculateOrGetTheAmountOfAirPerRowSide(y) | |
|| x > (xAxisPointsCount - calculateOrGetTheAmountOfAirPerRowSide(y)) | |
fun build() = ArrayList<String>().apply { | |
yAxisRange.forEach { y -> | |
add(StringBuilder().apply { | |
xAxisRange.forEach { x -> | |
append(if (isAir(x, y)) AIR else STONE) | |
} | |
}.toString()) | |
} | |
} | |
} | |
//endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment