Kotlin: Phone Bill calculator - kotlin

I'm new at kotlin. Now I'm trying to code a Phone Bill Calculator, when I have to charge user 0.25 for every minute they were over their plan, and 15% tax on subtotal. I can't find the 15% tax.
import java.util.*
fun main(args: Array<String>) {
var numberOfCalls: Int
val phoneBill: Float
val thetax: Float = 15f
val scan = Scanner(System.`in`)
print("Enter the Total Minutes of Calls Made this Month: ")
numberOfCalls = scan.nextInt()
if (numberOfCalls <= 60) phoneBill = 10f else {
numberOfCalls = numberOfCalls - 60
phoneBill = ((10 + (numberOfCalls * 0.25 )).toFloat() + (thetax/100))
}
println("\nTelephone Bill this Month = $phoneBill")
}

Instead of using this formula bill = total + total * tax you was using this bill = total + taxPercentage which is wrong, you can calculate it like that and have theTaxAmount separately ( you can use it somewhere ):
fun main(args: Array<String>) {
var numberOfCalls: Int
val phoneBill: Float
val theTaxPercentage: Float = 0.15f
val scan = Scanner(System.`in`)
print("Enter the Total Minutes of Calls Made this Month: ")
numberOfCalls = scan.nextInt()
if (numberOfCalls <= 60) phoneBill = 10f else {
numberOfCalls -= 60
val phoneBillWithoutTax = (10 + (numberOfCalls * 0.25 )).toFloat()
val theTaxAmount = phoneBillWithoutTax * theTaxPercentage
phoneBill = phoneBillWithoutTax + theTaxAmount
}
println("\nTelephone Bill this Month = $phoneBill")
}

Your algebra error is that you didn't multiply the tax by anything. You just added it like it was a flat rate of 15 cents. A tax by percentage is multiplied by the total amount. And an algebra tip: it's less math (and less code) to multiply something by 115% (1.15) than it is to figure out what 15% would be and add it to the original value.
I find it is easier (and has clearer code) to solve a problem by doing minimal number of steps at a time instead of setting up all your variables at the start and then modifying them. Create/initialize what you need only immediately before you will use it. Basically, if you can write your logic out of vals and no vars, usually this will be a cleaner solution.
fun main(args: Array<String>) {
print("Enter the Total Minutes of Calls Made this Month: ")
val scan = Scanner(System.`in`)
val numberOfMinutes = scan.nextInt()
var excessMinutes = numberOfMinutes - 60
if (excessMinutes < 0) {
excessMinutes = 0
}
val bill = 10 + excessMinutes * 0.25
val taxedBill = bill * 1.15
println("\nTelephone Bill this Month = $taxedBill")
}
The four lines of code for excessMinutes can be shortened as below, but I wrote it out verbosely since you are just learning how the basic logic works, and if you're doing this for a class, the teacher might not expect you to be using helper functions like that yet.
val excessMinutes = max(0, numberOfMinutes - 60)

Related

How to get the difference betweeen two dates (jetpack compose/kotlin)?

I have to calculate how many days are left between the date selected by the user through a DatePicker and the current date
I was trying to write something like this:
val simpleDate = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
val date = simpleDate.parse(event!!.date!!)
val diff = Duration.between(LocalDate.now(), date.toInstant())
val leftDays = diff.toDays()
Your mix of outdated (SimpleDateFormat, 'Date') and modern (LocalDate) APIs is not optimal, I think:
I would use plain java.time here, becauseā€¦
you can obviously use it in your application
it has a specific class for datetime Strings of the pattern you have shown in your question: an OffsetDateTime and
there's a java.time.Duration which you have tried to use
Here's an example:
fun main(args: Array<String>) {
// example input, some future datetime
val input = "2022-12-24T13:22:51.837Z"
// parse that future datetime
val offsetDateTime = OffsetDateTime.parse(input)
// build up a duration between the input and now, use the same class
val duration = Duration.between(OffsetDateTime.now(), offsetDateTime)
// get the difference in full days
val days = duration.toDays()
// print the result as "days left"
println("$days days left")
}
Output:
110 days left
If you don't receive a datetime but a date without time (just day of month, month of year and year), then use a LocalDate and calculate the ChronoUnit.DAYS.between(today, futureDate)
fun main(args: Array<String>) {
// example input, some future date
val input = "2022-12-24"
// parse that
val futureDate = LocalDate.parse(input)
// get the difference in full days
val days = ChronoUnit.DAYS.between(LocalDate.now(), futureDate)
// print the result
println("$days days left")
}
Output (again):
110 days left
Try below code -
val previousTimeDouble: Double = previousTime.toDouble()
val nowTimeDouble: Double = System.currentTimeMillis().toDouble()
val dateNowString: String = dateNow.toString();
val time: Long = (nowTimeDouble - previousTimeDouble).toLong()
val difference: String= differenceBetweenTwoTimes(time)
Log.d("difference", difference)
Function for converting time difference into units -
fun differenceBetweenTwoTimes(time: Long): String {
var x: Long = time / 1000
var seconds = x % 60
x /= 60
var minutes = x % 60
x /= 60
var hours = (x % 24).toInt()
x /= 24
var days = x
return String.format("%02d:%02d:%02d", hours, minutes, seconds)
}

Solo Learn practice how to calculate parking fee based on some conditions in Kotlin

You are making a car parking software that needs to calculate and output the amount due based on the number of hours the car was parked.
The fee is calculated based on the following price structure:
the first 5 hours are billed at $1 per hour.
after that, each hour is billed at $0.5 per hour.
for each 24 hours, there is a flat fee of $15.
This means, that, for example, if a car parked for 26 hours, the bill should be 15+(2*0.5) = 16.0, because it was parked for 24 hours plus 2 additional hours.
Sample Input:
8
Sample Output:
6.5
Explanation: The first 5 hours are billed at $1/hour, which results in $5. After that, the next 3 hours are billed at $0.5/hour = $1.5.
So, the total would be $5+$1.5 = $6.5
Below code works fine however it doesn't satisfy all conditions which are hidden
fun main(args: Array<String>) {
var hours = readLine()!!.toInt()
var total: Double = 0.0
total = when{
hours <= 5 -> {
val cost = hours *1.toDouble()
cost
}
hours in 6..23 -> {
val cost = 5 + (hours - 5) * 0.5
cost
}
hours == 24 -> {
val cost = 15.toDouble ()
cost
}
else -> {
val cost = 15 + (hours -24) * 0.5
cost
}
}
println(total )
}
One case that I think you missed is that, for hours > 24 you always use $15, while as per the question it is $15 per day, so you need to multiply it by the number of days.
Try this code:
fun main(args: Array<String>) {
val hours = readLine()!!.toInt()
val total = when {
hours >= 24 -> 15 * (hours / 24) + 0.5 * (hours % 24)
hours > 5 -> 5 + (hours - 5) * 0.5
else -> hours.toDouble()
}
println(total)
}
Try this code:
fun main (args : Array<String>) {
var hour = readLine()!!.toInt()
var total = when {
hour >= 24 -> (15 * (hour/24)) + (0.5 * (hour%24))
hour > 5 && hour <24 -> 5 + ((hour-5)*0.5)
else -> hour.toDouble()
}
println(total)
}

For loop must have an iterator()

I need this service in which if the person stays for longer than 30 minutes, they have to pay an extra $10 every 15 minutes (and for the fraction of the 15 as well).
I designed it like this so far:
var checkInTime: Calendar
val totalTime: Long
get() = (Calendar.getInstance().timeInMillis - checkInTime.timeInMillis) / MIN_IN_MILISEC
fun getTime(totalTime:Long): Int{
var finalPrice = 0
var initialPrice = 20
if(totalTime<31){
finalFee = initialPrice
} else {
val extraPrice = 10
val extraTime = 15
finalFee = initialPrice
for(extraTime in totalTime){
finalFee += extraTime
}
return finalFee
}
I get the error "For loop must have an iterator()" when I try to loop through the totalTime when it's more than 30 minutes so that I can add $10 every 15 extra minutes. I need some help as to how to add to the finalFee every extra 15 minutes the person stays since my method is not working.
Thank you.
Let's take a look at your getTime function:
You're using a Long as totalTime. You can measure it in minutes to simplify your calculation (since all time values are measured in minutes). Since a Long type in Kotlin stores a integer up to 9,223,372,036,854,775,807 and no soul on Earth will use your service for that long (this represents 17 billion milleniums), you can just use an Int.
You're not declaring the finalFee variable, thus the code will raise an
"Unresolved reference" error. Since you're not using the finalPrice variable, I'm assuming you wanted to use this instead.
You're trying to iterate over a numeric value (in this case, totalTime, which is a Long). You can iterate over each element of a List, but how would you iterate over each element of an integer? I'm assuming you want to do a certain action totalTime number of times. In this case, you would use ranges.
You're also not using the variables extraPrice and extraTime.
There's code that's common to both if-else conditions (finalPrice = initialPrice), so you can extract that to outside the if-statement.
Refactoring your function:
fun getTime(totalTime: Int): Int {
var finalPrice = 20
if (totalTime >= 30) {
(0 until totalTime).forEach {
finalPrice += 15
}
}
return finalPrice
}
It's shorter, but still doesn't do what it's supposed to: let's suppose totalTime is equal to 45. The person got 30 minutes costing $20 and only have to pay $10 for every 15 minutes, therefore will only pay $30 total. Your function is considering that the person will have to pay $15 for every minute they stayed, because it uses a for-loop that goes from 0 to totalTime. For that, you need a for-loop that goes from 30 (the time limit) from the total time (the totalTime) every 15 minutes:
fun getTime(totalTime: Int): Int {
var finalPrice = 20
if (totalTime > 30) {
(30 until totalTime step 15).forEach {
finalPrice += 10
}
}
return finalPrice
}
Better yet, you don't even need a for-loop, you can just use maths:
fun getTime(totalTime: Int): Int {
var finalPrice = 20
if (totalTime > 30) {
finalPrice += ((totalTime - 30) / 15) * 10
// ^^^^^^^^^^^^^^^^ Get the exceeding time
// ^^^^^^^^^^^^^^^^^^^^^^^ How many 15 minutes are there?
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Put $10 for every 15 minutes
}
return finalPrice
}
The last part: your question said you need to consider the fraction of 15 as well. Therefore, you need to use a real value, not an integer. Let's change it to a Double:
fun getTime(totalTime: Int): Double {
var finalPrice = 20.0
if (totalTime > 30) {
finalPrice += ((totalTime - 30) / 15.0) * 10
}
return finalPrice
}
Let's test your function:
fun main() {
println(getTime(0)) // Outputs 20.0
println(getTime(10)) // Outputs 20.0
println(getTime(30)) // Outputs 20.0
println(getTime(45)) // Outputs 30.0
println(getTime(60)) // Outputs 40.0
println(getTime(70)) // Outputs 46.666...
}

Rounding error down when not adding a round number using RoundingMode HALF_UP in Kotlin

consider below method:
fun main() {
var costs = 0
var transactionFee = 1.325
var total = (costs + transactionFee).toRoundedUpDouble()
}
fun Double.toRoundedUpDouble(fraction: Int = 2) =
BigDecimal(this).setScale(fraction, RoundingMode.HALF_UP).toDouble()
I want a number with 2 decimal after the comma, rounded up from 5. e.g. 1.325 becomes 1.33. This works when I add a round number, but not when I don't:
Output:
5.00 + 1.325 becomes 6.33 = good
5 + 1.325 becomes 6.33 = good
1 + 1.325 becomes 2.33 = good
1.325 becomes 1.32 = NOT GOOD
0 + 1.325 becomes 1.32 = NOT GOOD
0.00 + 1.325 becomes 1.32 = NOT GOOD
0.000 + 1.325 becomes 1.32 = NOT GOOD
This thread doesn't answer my question.
You say that this thread doesn't answer your question, but I it really does.
As mentioned in that thread, double literals lie to you, and println as well.
To know the actual value that these literals give you, you can use BigDecimal this way:
println(BigDecimal(1.325)) // 1.3249999999999999555910790149937383830547332763671875
println(BigDecimal(0 + 1.325)) // 1.3249999999999999555910790149937383830547332763671875
println(BigDecimal(5 + 1.325)) // 6.32500000000000017763568394002504646778106689453125
If you want accurate results, use BigDecimal from the start, and make sure to initialize them with strings, not double literals:
fun main() {
var costs = BigDecimal.ZERO
var transactionFee = BigDecimal("1.325")
var total = (costs + transactionFee).roundedUp()
println(total) // 1.33
println(total.toDouble()) // 1.33
}
fun BigDecimal.roundedUp(fraction: Int = 2) = setScale(fraction, RoundingMode.HALF_UP)

Kotlin - get sum of all element in a List [duplicate]

This question already has answers here:
Sum a subset of of numbers in a list
(3 answers)
Closed 2 years ago.
I have a List define as val tripList: List<Trip>
Here is my trip class
data class Trip(
val driver: Driver,
val passengers: Set<Passenger>,
// the trip duration in minutes
val duration: Int,
// the trip distance in km
val distance: Double,
// the percentage of discount (in 0.0..1.0 if not null)
val discount: Double? = null
){// the total cost of the trip
val cost: Double
get() = (1 - (discount ?: 0.0)) * (duration + distance)}
I want to calculate sum of all trip.cost in above tripList list.
Can any body suggest a way?
You can do this:
tripList.sumBy { it.cost }
Edit: then if Double use this:
tripList.sumByDouble { it.cost }
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sum-by-double.html