Created
March 12, 2020 15:43
-
-
Save cdmunoz/db7f78f6079bec98e6c225a9ad7b45b2 to your computer and use it in GitHub Desktop.
Solution to Hackerrank's Stock Open/Close Problem
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
package vanhack | |
import com.google.gson.Gson | |
import java.io.File | |
import java.io.InputStreamReader | |
import java.time.LocalDate | |
import java.time.Month | |
import java.time.format.DateTimeFormatter | |
import java.util.* | |
internal class Stock { | |
var date: String = "" | |
var open: Float = 0f | |
var close: Float = 0f | |
var high: Float = 0f | |
var low: Float = 0f | |
} | |
internal class StockPrice(private val stocks: Array<Stock>?) : StockInterface { | |
override fun openAndClosePrices(firstDate: String?, lastDate: String?, weekday: String?): List<Stock> { | |
val startDay = LocalDate.of(2000, Month.JANUARY, 5) | |
val endDay = LocalDate.of(2014, Month.JANUARY, 1) | |
val timeFormat = DateTimeFormatter.ofPattern("d-MMMM-yyyy", Locale.US) | |
val stockList = ArrayList<Stock>() | |
try { | |
var date01 = LocalDate.parse(firstDate!!, timeFormat) | |
var date02 = LocalDate.parse(lastDate!!, timeFormat) | |
var tempDate: LocalDate | |
val contWeekDays = arrayOf("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") | |
if (date01.isBefore(startDay)) { | |
date01 = startDay | |
} | |
if (date02.isAfter(endDay)) { | |
date02 = endDay | |
} | |
if (!Arrays.asList(*contWeekDays).contains(weekday)) { | |
println("Invalid parameter") | |
} else { | |
stocks?.let { | |
for (stock in stocks) { | |
tempDate = LocalDate.parse(stock.date, timeFormat) | |
if ((tempDate.isAfter(date01) || tempDate.isEqual(date01)) && (tempDate.isBefore(date02) || tempDate.isEqual(date02))) { | |
val dayOfWeekRecord = tempDate.dayOfWeek.value | |
val dayOfWeekParam = getDayOfWeekOrdinalFromName(weekday!!, contWeekDays) | |
if (dayOfWeekRecord == dayOfWeekParam) { | |
stockList.add(stock) | |
} | |
} | |
} | |
} | |
} | |
} catch (ex: Exception) { | |
println(ex.message) | |
} | |
return stockList | |
} | |
private fun getDayOfWeekOrdinalFromName(name: String, daysOfWeek: Array<String>): Int { | |
var dayOfWeekOrdinal = 0 | |
if (Arrays.asList(*daysOfWeek).contains(name)) { | |
for (i in 0 until daysOfWeek.size - 1) { | |
if (daysOfWeek[i].toLowerCase() == name.toLowerCase()) { | |
dayOfWeekOrdinal = i | |
break | |
} | |
} | |
} | |
return dayOfWeekOrdinal + 1 | |
} | |
} | |
fun main(args: Array<String>) { | |
val `in` = Scanner(System.`in`) | |
val firstDate: String? | |
firstDate = `in`.nextLine() | |
if (firstDate.isNullOrBlank() || !Utils.isDateDayOfTheMonthValid(firstDate)) { | |
println("Invalid parameter.") | |
throw InvalidParameterException("Invalid parameter.") | |
} | |
val lastDate: String? | |
lastDate = `in`.nextLine() | |
if (lastDate.isNullOrBlank() || !Utils.isDateDayOfTheMonthValid(lastDate)) { | |
println("Invalid parameter.") | |
throw InvalidParameterException("Invalid parameter.") | |
} | |
val weekDay: String? | |
weekDay = `in`.nextLine() | |
if (weekDay.isNullOrBlank() || !Utils.isWeekday(weekDay)) { | |
println("Invalid parameter.") | |
throw InvalidParameterException("Invalid parameter.") | |
} | |
if (Utils.isFirstDateBeforeLastDate(firstDate, lastDate)) { | |
println("Invalid parameter.") | |
throw InvalidParameterException("Invalid parameter.") | |
} | |
try { | |
//get stocks info from data.json | |
//For local IntelliJ | |
/*val path = Stock::class.java.getResource("./data.json") | |
val reader = InputStreamReader(path.openStream())*/ | |
//For Hackerrank | |
val file = File("./data.json") | |
val reader = InputStreamReader(file.inputStream()) | |
val stocks = Gson().fromJson(reader, Array<Stock>::class.java) | |
if (null == stocks || stocks.isEmpty()) { | |
throw NoStockException("Stock not found.") | |
} else { | |
val stockPrice: StockInterface = StockPrice(stocks) | |
val stocklist = stockPrice.openAndClosePrices(firstDate, lastDate, weekDay) | |
for (stock in stocklist) | |
println(stock.date + " " + stock.open + " " + stock.close) | |
} | |
} catch (ex: Exception) { | |
println(ex.message) | |
} | |
} | |
internal class Utils { | |
companion object { | |
private val weekdays = arrayListOf("Monday", "Tuesday", "Wednesday", "Thursday", "Friday") | |
fun isDateDayOfTheMonthValid(date: String?): Boolean { | |
date?.let { theDate -> | |
val dayOfTheMonthValue = theDate.substring(0, theDate.indexOf("-")) | |
return dayOfTheMonthValue.toInt() <= 31 | |
} | |
return false | |
} | |
fun isWeekday(weekday: String?): Boolean { | |
weekday?.let { | |
if (weekdays.contains(weekday)) return true | |
} | |
return false | |
} | |
fun isFirstDateBeforeLastDate(firstDate: String?, lastDate: String?): Boolean { | |
val timeFormat = DateTimeFormatter.ofPattern("d-MMMM-yyyy", Locale.US) | |
try { | |
val date01 = LocalDate.parse(firstDate!!, timeFormat) | |
val date02 = LocalDate.parse(lastDate!!, timeFormat) | |
return date01.isAfter(date02) | |
} catch (ex: Exception) { | |
println(ex.message) | |
println(ex.message) | |
} | |
return false | |
} | |
} | |
} | |
internal interface StockInterface { | |
fun openAndClosePrices(firstDate: String?, lastDate: String?, weekday: String?): List<Stock> | |
} | |
internal class NoStockException(message: String) : Exception(message) | |
internal class InvalidParameterException(message: String) : Exception(message) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment