For loop must have an iterator() - kotlin

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...
}

Related

how to perform dynamic subtraction of a list of numbers with a specific value

My idea is to subtract each value from my list through the value of a variable, for example:
var subtraction = 250
var list = mutableListOf(300, 200, 100)
Then, using the 250 of the subtraction variable,
you can dynamically subtract each value of the item,
from the last to the first, so with that 250 the program should return: -> list(300, 50).
Where 250 is subtracted from item 100 (last item) and then "150" remains from the value "250",
and the remaining 150 is subtracted from 200 (second item) and remains 50,
thus zeroing out the value of "250" and the program stop.
Getting (300, 50) -> 50 which comes from 200 (second item).
As if I was going through my list of numbers, subtracting item by item through the value of a variable, from last to first.
Your question still needs further clarification:
What should be the output if subtraction = 700?
What should be the output if subtraction = 600?
What should be the output if subtraction = 100?
The following can be a starting point to solve your question:
fun subtraction() {
var subtraction = 250
var list = mutableListOf(300, 200, 100)
// Loop the list in Reverse order
for (number in list.indices.reversed()) {
subtraction -= list[number] // Subtract the last number
// If subtraction is greater than zero, continue and remove the last element
if (subtraction > 0)
list.removeAt(number)
else {
// It subtraction is less than or equal to zero,
// remove the last element, append the final subtraction result,
// and stop the loop
list.removeAt(number)
list.add(abs(subtraction))
break
}
}
// If the subtraction result is still positive after whole list has been processed,
// append it back to the list
// if (subtraction > 0)
// list.add(subtraction)
println(list)
}
Output
[300, 50]
The question isn't very clear, but as I understand it: OP wants to modify a list of numbers, subtracting a fixed amount from each, and removing those for which the result would be negative.
If so, it can be done very simply:
list.replaceAll{ it - subtraction }
list.removeIf{ it < 0 }
However, instead of mutating the existing list, it would probably be more common to create a new one:
val newList = list.map{ it - subtraction }.filter{ it >= 0 }
Or, if you need to avoid creating a temporary list:
val newList = list.mapNotNull{ (it - subtraction).takeIf{ it >= 0 } }
A solution with foldRight using a Pair as accumulator:
val list = listOf(300, 200, 100)
val subtraction = 250
val result = list
.foldRight(subtraction to emptyList<Int>()) { item, (diff, list) ->
when {
diff > item -> diff - item to emptyList()
else -> 0 to listOf(item - diff) + list
}
}
.second
println(result) // Output: [300, 50]

Kotlin: Phone Bill calculator

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)

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)
}

Kotlin/Java formatting Double values

My current formatting is this
DecimalFormat("#,##0.00").format(value)
I need to handle values like this
0.00 //ok
0.45 //ok
0.002 //Need to show 0.002 or 0.0020
0.0003 //Need to show 0.0003 or 0.00030
0.00004 //Need to show 0.00004 or 0.000040
0.00234567 //Need to show 0.0023
But sure the above code will not work on fractional part where a non zero value started at thousandth place else I will just ended up displaying 0.00 as if it is totally a zero value. I still want the above formatting with comma when dealing with whole number but also allowing me to format when non zero starts beyond hundredths place.
Further sample
0.0492 // 0.04 or 0.05 much better
700.356 // 700.35 or 700.36 much better
54232.542234 // 54,232.54
Try multiplying the number by 10 until you know you got to two non zero digits. This way you will get the number of decimal points you have to round up.
After that you use the NumberFormat to format the number like this:
val format = NumberFormat.getInstance()
format.maximumFractionDigits = nrOfDecimalPoints
val formattedNumber = format.format(yourNumber)
This way you will keep the thousands separator "," and the decimal will be cut off after two non zero digits.
EDIT
This is how the custom function looks like:
private fun customFormat(number: Double): String{
var temp = number - number.toInt()
temp *= 100
var nrDec = 2
if (number <= 0.0){
return "0.00"
}
if (temp >= 1.0){
val format = NumberFormat.getInstance(Locale.US)
format.maximumFractionDigits = nrDec
return format.format(number)
}
while (temp < 1.0 && nrDec < 15){
temp *= 10
nrDec ++
}
if((temp * 10 % 10) != 0.0){
nrDec++
}
val format = NumberFormat.getInstance(Locale.US)
format.maximumFractionDigits = nrDec
return format.format(number)
}
You can do it like this in order to cut of tailing 0:
public static void main(String []args){
double number1 = 0.2;
double number2 = 1.55;
double number3 = 0.00005;
double number4 = 0.50000;
DecimalFormat df = new DecimalFormat("###,##0.00#########");
System.out.println(df.format(number1)); // 0.20
System.out.println(df.format(number2)); // 1.55
System.out.println(df.format(number3)); // 0.00005
System.out.println(df.format(number4)); // 0.50
}
You just need to know how far your decimal digits should be checked.

How to meet properly if condition

I'm having a problem with this task. My goal is to calculate car price providing its mileage.
The formula is:
price lowers by 200$ for every 10000 kilometers that the car passed. For example, for 19999 km the price decreases by 200 dollars, but for 20000 km the price lowers by 400 dollars. And additionally the prices lowers due to car's age multiplied by 200.
What I did is:
when (input) {
in 0..9999 -> {
moneyToRemove = 2000
price -= moneyToRemove
}
else -> {
var counter = 0
moneyToRemove = old * 2000
for (x in 10000..input) {
if (x % 10000 == 0 ) {
counter++
if (x == input) {
println(counter)
price = price - moneyToRemove - counter*200
}
}
}
}
}
input - mileage provided from scanner
In first when condition moneyToRemove variable is set to 2000 ( 5years *200)
In else condition I tried to count how many extra dollars will lower the car price using counter. But then I have a problem with e.g. value 299 999. The counter in debugger mode shows 29 which is correct, but I can't meet the second condition and properly count car's price. Can you help?
This is from JetBrains academy Kotlin dev track.
You don't need any if conditions for that. You can put it in a simple formula
import kotlin.math.*
fun main() {
var originalprice = 30000; // the original price
var miles = 12345.6; // the mileage
var age = 7; //the age in years
var reducedprice = originalprice -
(floor(miles / 10000.0)) * 200 - //substract 200$ for each full 10000 miles
age * 200 //substract 200$ foreach year
print(reducedprice);
}
floor(miles/ 10000.0) will divide the miles by 10000 and round it downwards to the next integer. So it will be 0 for 0-9999, 1 for 10000 - 19999 and so on ... floor
If miles is an integer value, you don't even need floor, because the integer division will only return whole numbers. Ie 9999/10000 = 0, 19999/10000 = 1 and so on ...
var reducedprice = originalprice -
(miles / 10000) * 200 - //substract 200$ for each full 10000 miles
age * 200 //substract 200$ foreach year
EDIT
Eventhough I consider your approach as quite complicated and not easily maintainable
You have code duplication for the age part,
You do a lot of unnecessary % calculations for each value from 10000 up to your input
The when isn't necessary, because all the code exectued in the first branch is also executed in the second branch. Just could just do the loop, starting at 10000, so if the input is < 10000 it won't be executed ...
But all in all, your approach will in principle work too. But there are two issues with it
You don't consider the age of the car, when the mileage is below 10000, but you just withdraw a fixed amount.
When the mileage is above 10000, you calculate the reduced price only if the input is an exact multiple of 10000. You must put that calculation after the loop.
when (input) {
in 0..9999 -> {
moneyToRemove = old * 2000
price -= moneyToRemove
}
else -> {
moneyToRemove = old * 2000
for (x in 10000..input) {
if (x % 10000 == 0 ) {
moneyToRemove += 200
}
}
println(counter)
price -= moneyToRemove
}
}