How to add spaces between numbers with Kotlin - kotlin

How can I format string "2000000.00" into "2 000 000.00" with Kotlin?

You can do this with DecimalFormat():
val dec = DecimalFormat(<pattern> [, <optional, but recommended locale>])
and then replace , with :
val number = 2000000.00
val dec = DecimalFormat("###,###,###,###,###.00", DecimalFormatSymbols(Locale.ENGLISH))
val formattedNumber = dec.format(number).replace(",", " ")
println(formattedNumber)
.00 is needed to keep the digits!!!
This will print:
2 000 000.00
here as a test:
#Test
fun testDecimalFormat() {
val number = 2000000.00
val dec = DecimalFormat("###,###,###,###,###.00", DecimalFormatSymbols(Locale.ENGLISH))
val formattedNumber = dec.format(number).replace(",", " ")
assertThat(formattedNumber).isEqualTo("2 000 000.00")
}
#Test
fun testDecimalFormatWithDigitValue() {
val number = 2000000.01
val dec = DecimalFormat("###,###,###,###,###.00", DecimalFormatSymbols(Locale.ENGLISH))
val formattedNumber = dec.format(number).replace(",", " ")
assertThat(formattedNumber).isEqualTo("2 000 000.01")
}
Link: https://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html

Related

Evaluating a string in kotlin

I wrote a code in kotlin for evaluating a given string from Divison to subtraction, it works but it gives the wrong answer, for example i got a string x in the first line which have answer -215.96666 whereas the answer from code is -237.366666 idk where the error is. i saw more people using stack for doing it, but i wanted to do this way for evaluating a string
var x : String = "5+4-10x20-40/30x20+34/20"
fun div(x: String): String {
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if ("/" in ele1) {
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for (ele2 in lis2) {
if ("/" in ele2) {
val pos3 = lis2.indexOf(ele2)
val lis3 = ele2.split("x").toMutableList()
for (ele3 in lis3) {
if ("/" in ele3) {
val pos4 = lis3.indexOf(ele3)
val lis4 = ele3.split("/")
val div = (lis4[0].toDouble() / lis4[1].toDouble()).toString()
lis3[pos4] = div
}
}
lis2[pos3] = lis3.joinToString("x")
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun mul(x : String) : String{
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if("x" in ele1){
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for(ele2 in lis2){
if("x" in ele2){
val pos2 = lis2.indexOf(ele2)
val lis3 = ele2.split("x")
val mul = (lis3[0].toDouble() * lis3[1].toDouble()).toString()
lis2[pos2] = mul
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun add(x : String): String {
val lis1 = x.split("-").toMutableList()
for(ele1 in lis1){
if("+" in ele1){
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+")
val add = (lis2[0].toDouble() + lis2[1].toDouble()).toString()
lis1[pos1] = add
}
}
return (lis1.joinToString("-"))
}
fun sub(x : String) : String{
val lis1 = x.split("-").toMutableList()
var sub = 0.0
for(ele1 in lis1){
sub -= ele1.toDouble()
}
return (sub.toString())
}
fun eval(x: String): String {
val divanswer = div(x)
val mulanswer = mul(divanswer)
val addanswer = add(mulanswer)
return sub(addanswer)
}
fun main(args: Array<String>){
println(eval(x))
}
i wanted the answer as -215.96666 but the answer given by code is -237.366666
In the case of this specific input, there are two bugs involved.
First bug is related to the fact you first process + and then -, but in mathematics we should process them together, from left to right. As a result, your algorithm processes this: 1-1+1 (correct answer: 1) as: 1-(1+1) (answer: -1). Alternatively, I believe handling - first and then + should work properly.
Second bug is that in sub() you start from 0 and subtract even the first number, but the first number should be actually added or used as an initial value.
I believe after fixing these two bugs, it should provide a correct answer for this specific input, but there are probably more bugs like these. For example, you incorrectly handle chains of the same operator, you only care about the first pair, so 1+1+1 becomes 2 (and then it is turned to -2 due to earlier mentioned bug).
As a general advice, learn to use a debugger and analyze how your data changes while your code is processing it. Even if you simply print your intermediate results: divanswer, mulanswer and addanswer and then run them through Google for processing, you will notice there is a problem somewhere at the add() step. Then rinse and repeat until everything works correctly.
Thanks to #broot for spotting this, the problem was with the addition and subtraction part, now that i merged them into one and got the correct answers for strings i input, here is the full code corrected.
var x : String = "5+4-10x20-40/30x20+34/20"
fun div(x: String): String {
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if ("/" in ele1) {
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for (ele2 in lis2) {
if ("/" in ele2) {
val pos3 = lis2.indexOf(ele2)
val lis3 = ele2.split("x").toMutableList()
for (ele3 in lis3) {
if ("/" in ele3) {
val pos4 = lis3.indexOf(ele3)
val lis4 = ele3.split("/")
val div = (lis4[0].toDouble() / lis4[1].toDouble()).toString()
lis3[pos4] = div
}
}
lis2[pos3] = lis3.joinToString("x")
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun mul(x : String) : String{
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if("x" in ele1){
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for(ele2 in lis2){
if("x" in ele2){
val pos2 = lis2.indexOf(ele2)
val lis3 = ele2.split("x")
val mul = (lis3[0].toDouble() * lis3[1].toDouble()).toString()
lis2[pos2] = mul
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun final(x: String): Double {
val substr = StringBuffer()
var answer = 0.0
var opr = '+'
for(ele in x.indices){
var current = x[ele]
if(current in '0'..'9' || current == '.'){
substr.append(current)
}
if(current == '-' || current == '+'){
var operand = substr.toString().toDouble()
substr.setLength(0)
when (opr){
'+' -> answer += operand
'-' -> answer -= operand
}
opr = current
}
}
val num = substr.toString().toDouble()
when(opr){
'+' -> answer += num
'-' -> answer -= num
}
return answer
}
fun eval(x: String): Double {
val divanswer = div(x)
return final(mul(divanswer))
}
fun main(args: Array<String>){
println(eval(x))
}

Format number based on pattern

I need to format numbers based on pattern given in the code.
Number : 12038902.9, Pattern : "##,###,###.##". Output must be like : 12,038,902.9 I have to use this "##,###,###.##" & "##.###.###,##" also.
I have tried this but not working :
fun main() {
val number = 12038902.90
val pattern = "##,###,###.##"
val formattedNumber = formatNumber(number, pattern)
println(formattedNumber)
}
fun formatNumber(number: Double, pattern: String): String {
val parts = pattern.split(".")
val integerPart = parts[0].replace(",", "")
val decimalPartFormat = parts[1]
val intPartFormat = "%d"
val decimalPartForm = "%.${decimalPartFormat.length}f"
val formattedIntPart = String.format(intPartFormat, number.toInt()).replaceFirst("(?<=\\d)(?=(\\d{3})+(?!\\d))".toRegex(), ",")
val decimalPart = (number * 10.0.pow(decimalPartFormat.length)).toInt() % 10.0.pow(decimalPartFormat.length).toInt()
val formattedDecimalPart = String.format("%0${decimalPartFormat.length}d", decimalPart).replaceFirst("0*$".toRegex(), "").replaceFirst("(?<=\\d)(?=(\\d{3})+(?!\\d))".toRegex(), ",")
return "$formattedIntPart.$formattedDecimalPart"
}
Getting this output : 12,038902.9 which is wrong I want is 12,038,902.9:
Pattern & number both are dynamic so I need to adjust as per it's need.
maybe u can use DecimalFormat for this purpose. It takes care of grouping, proper separators etc.
Result for your the input 12038902.9 is: 12,038,902.9
fun convert(number: String) {
val decimalFormatSymbols = DecimalFormatSymbols()
decimalFormatSymbols.decimalSeparator = '.'
decimalFormatSymbols.groupingSeparator = ','
val decimalFormat = DecimalFormat()
decimalFormat.decimalFormatSymbols = decimalFormatSymbols
decimalFormat.groupingSize = 3
decimalFormat.maximumFractionDigits = 2
decimalFormat.minimumFractionDigits = 1
decimalFormat.maximumIntegerDigits = 8
decimalFormat.maximumIntegerDigits = 8
val formattedNumber = decimalFormat.format(number.toDoube())
println(formattedNumber)
}
Try with:
val number = 12038902.9
val pattern = "##,###,###.##"
val formattedNumber = DecimalFormat(pattern).format(number)

Remove character or word from string in kotlin

Hey I want to remove character/word or sentence from string.
For example
val string = "Hey 123"
or
val string = "Hey How are you 123"
or
val string = "Hey!! How are you 123"
and output
string = 123
If you only want the digits:
val result = string.filter { it.isDigit() }
Alternatively if you want to omit letters (and maybe also whitespace):
val result = string.filter { !it.isLetter() }
val result = string.filter { !it.isLetter() && !it.isWhitespace() }

Setter not assigning value in Kotlin

I am trying to do a temperature program, which outputs the lowest temperature from three cities provided. If the temperature of one of three cities is above + 57 or below -92 all three cities will have set default values which are (+5 Moscow, +20 Hanoi , 30 for Dubai)
However providing those numbers 20,100,35 in readLine doesn't work.
This is how City class looks like:
class City(val name: String) {
var degrees: Int = 0
set(value) {
field =
if (value > 57 || -92 > value) {
when (this.name) {
"Dubai" -> 30
"Moscow" -> 5
"Hanoi" -> 20
else -> 0
}
} else {
value
}
}}
And in my main I have:
val first = readLine()!!.toInt()
val second = readLine()!!.toInt()
val third = readLine()!!.toInt()
val firstCity = City("Dubai")
val secondCity = City("Moscow")
val thirdCity = City("Hanoi")
firstCity.degrees = first
secondCity.degrees = second
thirdCity.degrees = third
println(first)
println(second)
println(third)
What's wrong in the setter? Why does the second doesn't set the default values?
Works as expected to me https://pl.kotl.in/otINdg8E3:
class City(val name: String) {
var degrees: Int = 0
set(value) {
field =
if (value > 57 || -92 > value) {
when (this.name) {
"Dubai" -> 30
"Moscow" -> 5
"Hanoi" -> 20
else -> 0
}
} else {
value
}
}}
fun main() {
val firstCity = City("Dubai")
val secondCity = City("Moscow")
val thirdCity = City("Hanoi")
firstCity.degrees = 100
secondCity.degrees = -100
thirdCity.degrees = 6
println(firstCity.degrees) // prints 30
println(secondCity.degrees) // prints 5
println(thirdCity.degrees) // prints 6
}

Spark code to read property and define logger and multi threading

Below is the code to run spark code in thread
we can run spark task on parallel below code is example to run using thread
spark dataframe pass query to run future will help to run parallel
Added logger file and property file to read property
package Test
import java.util.concurrent.Executors
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession
import scala.io.Source.fromFile
import org.apache.log4j.Logger
object ParallerlExecution {
val log = Logger.getLogger(getClass.getName)
def main(args: Array[String]): Unit = {
log.info("Start of program!!")
val queryList=loadFile()
parallerlExecution(queryList)
log.info("End of program!!!")
}
def loadFile():List[String]={
fromFile("").getLines().toList
}
def parallerlExecution(queryList:List[String]): Unit ={
val spark=SparkSession.builder().appName("test").master("local[*]").getOrCreate()
/*
--properties-file parallelprop.conf
create file and put info like below
spark.jdbc.url <jdbc url >
spark.jdbc.username <user name for db>
spark.jdbc.password <password for db>
*/
val url=spark.sparkContext.getConf.get("spark.jdbc.url")
val username=spark.sparkContext.getConf.get("spark.jdbc.username")
val password=spark.sparkContext.getConf.get("spark.jdbc.password")
val pool= Executors.newFixedThreadPool(3)
for(query<-queryList){
val r= new Runnable {
override def run(): Unit = {
val st = System.currentTimeMillis();
val df = spark.read
.format("jdbc")
.option("url", "jdbc:postgresql:dbserver")
.option("dbtable", query)
.option("user", username)
.option("password", password)
.load()
val count = df.count
val et = System.currentTimeMillis();
val resIntoHdfs=spark.sparkContext.parallelize( Seq(url,count))
resIntoHdfs.coalesce(1).saveAsTextFile("hdfs path to write result example /user/abc/"+et)
val rddOfDataframe = df.rdd.map(_.toString())
val size = calcRDDSize(rddOfDataframe)
val logInput="Thread" + Thread.currentThread().getId() + " Record Count " + count + " StartTime " + st + " Endtime " + et +" Size: "+size+ " Query: " + query
case class LogOut(value:String)
import spark.implicits._
val logDF=spark.sparkContext.parallelize( Seq(LogOut(logInput))).toDF
logDF.coalesce(1).write.mode("append").save("hdfs path to save result example /home/abc/logsqlresult")
println("Thread" + Thread.currentThread().getId() + " Record Count " + count + " StartTime " + st + " Endtime " + et +" Size: "+size+ " Query: " + query)
log.info(logInput)
}
}
pool.execute(r)
}
pool.shutdown()
}
def calcRDDSize(rdd: RDD[String]): Long = {
rdd.map(_.getBytes("UTF-8").length.toLong)
.reduce(_+_) //add the sizes together
}
}
we can run spark in multi threading defined thread pool and in loop we can run our spark program in parallel mode
package Test
import java.io.{BufferedReader, InputStreamReader}
import java.util.concurrent.Executors
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession
import scala.io.Source.fromFile
import org.apache.log4j.Logger
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.security.alias.CredentialProviderFactory
import java.util.Properties
import org.apache.hadoop.fs.FSInputStream
import org.apache.hadoop.fs.FileSystem
import org.apache.hadoop.fs.Path
object ParallerlExecution {
val log = Logger.getLogger(getClass.getName)
def main(args: Array[String]): Unit = {
val hdfsFilePath=args(0)
log.info("Start of program!!")
val queryList=load_file("")
parallerlExecution(queryList,hdfsFilePath)
log.info("End of program!!!")
}
/* def loadFile():List[String]={
fromFile("").getLines().toList
}
*/
def load_file(path:String)={
val pt=new Path(path)
val fs = FileSystem.get(new Configuration())
val br=new BufferedReader(new InputStreamReader(fs.open(pt)))
var res:List[String]= List()
try {
var line=br.readLine()
while (line != null){
System.out.println(line);
res= res :+ line
line=br.readLine()
}
} finally {
// you should close out the BufferedReader
br.close();
}
res
}
def parallerlExecution(queryList:List[String],hdfsFilePath:String): Unit ={
val spark=SparkSession.builder().appName("test").master("local[*]").getOrCreate()
/*
--properties-file parallelprop.conf
create file and put info like below
spark.jdbc.url <jdbc url >
spark.jdbc.username <user name for db>
spark.jdbc.password <password for db>
*/
/*val url=spark.sparkContext.getConf.get("spark.jdbc.url")
val username=spark.sparkContext.getConf.get("spark.jdbc.username")
val jecksProvider=spark.sparkContext.getConf.get("spark.jecks.provider")
val passwordAlial=spark.sparkContext.getConf.get("spark.password.alias")*/
val prop=readHdfsFile(hdfsFilePath)
val jecksProvider=prop.getProperty("jeck-provider")
val passwordAlial=prop.getProperty("password-alias")
val url=prop.getProperty("url")
val username=prop.getProperty("username")
val password=extractPwdFromJceks(jecksProvider,passwordAlial)
val pool= Executors.newFixedThreadPool(3)
for(query<-queryList){
val r= new Runnable {
override def run(): Unit = {
val st = System.currentTimeMillis();
val tableName=""
val df = spark.read
.format("jdbc")
.option("url", "jdbc:postgresql:dbserver")
.option("dbtable", query)
.option("user", username)
.option("password", password)
.load()
val count = df.count
val et = System.currentTimeMillis();
val resIntoHdfs=spark.sparkContext.parallelize( Seq(url,count))
resIntoHdfs.coalesce(1).saveAsTextFile("hdfs path to write result example /user/abc/"+et)
val rddOfDataframe = df.rdd.map(_.toString())
val size = calcRDDSize(rddOfDataframe)
val logInput="Thread" + Thread.currentThread().getId() + " Record Count " + count + " StartTime " + st + " Endtime " + et +" Size: "+size+ " Query: " + query
case class LogOut(value:String)
import spark.implicits._
case class Out(tableName:String,sizeOfData:String)
df.write.mode("overwrite").save("<path hdfs>"+tableName)
val sizeOfData=getFileSizeByPath("<path hdfs>"+tableName)
val outDF=spark.sparkContext.parallelize( Seq(Out(tableName,sizeOfData.toString))).toDF
outDF.coalesce(1).write.mode("append").csv("hdfs path to save result ")
println("Thread" + Thread.currentThread().getId() + " Record Count " + count + " StartTime " + st + " Endtime " + et +" Size: "+size+ " Query: " + query)
log.info(logInput)
}
}
pool.execute(r)
}
pool.shutdown()
}
def calcRDDSize(rdd: RDD[String]): Long = {
rdd.map(_.getBytes("UTF-8").length.toLong)
.reduce(_+_) //add the sizes together
}
def extractPwdFromJceks(jceksfile:String, password_alias:String):String = {
val conf:Configuration = new Configuration()
conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, jceksfile)
conf.getPassword(password_alias).mkString("")
}
def readHdfsFile(path:String):Properties={
val prop=new Properties()
val fis=FileSystem.get(new Configuration()).open(new Path(path))
prop.load(fis)
prop
}
private def getFileSizeByPath(filePath : String): Long = {
val path = new Path(filePath)
val hdfs = path.getFileSystem(new Configuration())
val cSummary = hdfs.getContentSummary(path)
val length = cSummary.getLength
length
}
}