I have a number in minutes, for example:
Int totalminutes= 342
I want to dispaly it like this:
5h:42m:..s
I did a scala function to convert the minute to hour and return HH:MM:SS
scala> def convertSeconds(input:Int):String ={
| val totalMinutes = input/60
| val seconds = input%60
| val minutes = totalMinutes%60
| val hours = totalMinutes%60
|
| return "%sh:%sm:%ss".format(hours,minutes,seconds)
| }
convertSeconds: (input: Int)String
I did my tests:
scala> convertSeconds(120) // 120 minutes
res22: String = 2h:2m:0s // why it add 2 minutes
scala> convertSeconds(60) // 60 minutes
res23: String = 1h:1m:0s // adding 1 minute
scala> convertSeconds(36) // 36 minutes
res24: String = 0h:0m:36s // I want to return 0h:30m:06s
The solution is:
scala> def convertSeconds(input:Int):String ={
//val totalMinutes = input/60
//val seconds = input/60%60
val minutes = input%60
val hours = input/60
return "%sh:%sm".format(hours,minutes)
}
convertSeconds: (input: Int)String
scala> convertSeconds(36)
res57: String = 0h:36m
scala> convertSeconds(120)
res58: String = 2h:0m
scala> convertSeconds(122)
res59: String = 2h:2m
scala> convertSeconds(2166)
res60: String = 36h:6m
Your function is supposed to be like this and you pass seconds not minutes:
def convertSeconds(input:Int):String ={
val hours = input/3600
val minutes = (input-hours*3600)/60
val seconds = input%3600-minutes*60
"%sh:%sm:%ss".format(hours,minutes,seconds)
}
If you want to pass minutes, the function should be something like this, I named it convertMinutes, and your seconds will zero, and you can get in your prescribed display by this code:
def convertMinutes(input:Int):String ={
val hours = input/60
val minutes = input-hours*60
"%sh:%sm:%ss".format(hours,minutes,"..")
}
In Scala REPL:
scala> convertSeconds(7523)
res4: String = 2h:5m:23s
scala> convertSeconds(9523)
res5: String = 2h:38m:43s
scala> convertSeconds(3724)
res6: String = 1h:2m:4s
scala> convertMinutes(342)
res10: String = 5h:42m:..s
I am not sure if you need a separate function to achieve this.
Scala already gives a library to do that
scala> val secs = 62
secs: Int = 62
scala> import scala.concurrent.duration._
scala> val inTime = Duration(secs,SECONDS)
inTime: scala.concurrent.duration.FiniteDuration = 62 seconds
scala> "%02d:%02d:%02d".format(inTime.toHours,inTime.toMinutes%60,inTime.toSeconds%60)
res8: String = 00:01:02
EDIT-1: What this does not handle is if you pass a number >= 86400 (total seconds in a day)
In Java, trusting you to translate yourself:
int totalminutes = 342;
Duration dur = Duration.ofMinutes(totalminutes);
String display = String.format("%dh:%02dm:%02ds",
dur.toHours(), dur.toMinutesPart(), dur.toSecondsPart());
System.out.println(display);
This prints:
5h:42m:00s
If had a number of seconds instead, use Duration.ofSeconds instead.
Don’t do the calculation yourself. It’s error-prone and it will require your reader to take some time to convince herself/himself that your calculation is correct. Instead let the library methods do the calculations, even when they seem trivial.
What went wrong in your code?
It’s been said already: You used
val hours = totalMinutes%60
This should have been a division:
val hours = totalMinutes / 60
It’s easier than you might expect to make such an error. For comparison you don’t that easily call toMinutesPart when you intended toHours, and if you still do, it’s easier to spot the bug.
Related
I'm making a simple program to make a calculation for a game I play. I tried 2 attempts and it wasn't working. I made all the variables doubles but I still get this odd result.
The values of actionTicks would be 1-10, skillLevel would be 1-99.
My current output is :
Your chance of receiving a pet is: 1.6E-6
Your chance is 0
Could someone explain why the result is wrong and how I'd fix it.
import scala.io.StdIn._
object PetRates {
def main(args: Array[String]): Unit = {
var baseDiv: Double = 50000000
println("Enter amount of ticks per action: ")
var actionTicks = readDouble()
println("Now enter your skill level: ")
var skillLvl = readDouble()
var result: Double = actionTicks*skillLvl
println("Your chance is: " + (result / baseDiv))
println("Your chance is " + ((8 * 10)/50000000) )
}
}
Your app appears to have delivered exactly what you're asking it to. It looks like you might be confused by the scientific notation:
scala> (8.0 * 10.0) / 50000000.0
// res1: Double = 1.6E-6
scala> 0.0000016
// res2: Double = 1.6E-6
As to (8 * 10) / 50000000, it's an integer division returning an integer (that rounds towards 0) since the operands are all Int type:
scala> (8 * 10) / 50000000
// res3: Int = 0
scala> 40000000 / 50000000
// res4: Int = 0
scala> 80000000 / 50000000
// res5: Int = 1
scala> -40000000 / 50000000
// res5: Int = 0
To add to Leo's answer, you can write either of the terms in fractions as a double so that the result is also double, like
(8.0 * 10)/50000000)
I am taking the Functional Programming in Scala course on Coursera and I am having a hard time understanding this code snippet -
def sqrtStream(x: Double): Stream[Double] = {
def improve(guess: Double): Double = (guess+ x/ guess) / 2
lazy val guesses: Stream[Double] = 1 #:: (guesses map improve)
guesses
}
This method would find 10 approximate square root of 4 in increasing order of accuracy when I would do sqrtSteam(4).take(10).toList.
Can someone explain the evaluation strategy of guesses here? My doubt is what value of guesses in substituted when the second value of guesses is picked up?
Let's start from simplified example:
scala> lazy val a: Int = a + 5
a: Int = <lazy>
scala> a
stack overflow here, because of infinite recursion
So a is recalculating til it gets some stable value, like here:
scala> def f(f:() => Any) = 0 //takes function with captured a - returns constant 0
f: (f: () => Any)Int
scala> lazy val a: Int = f(() => a) + 5
a: Int = <lazy>
scala> a
res4: Int = 5 // 0 + 5
You may replace def f(f:() => Any) = 0 with def f(f: => Any) = 0, so a definition will look like it's really passed to the f: lazy val a: Int = f(a) + 5.
Streams use same mechanism - guesses map improve will be passed as parameter called by name (and lambda linked to the lazy a will be saved inside Stream, but not calculated until tail is requested), so it's like lazy val guesses = #::(1, () => guesses map improve). When you call guessess.head - tail will not be evaluated; guesses.tail will lazily return Stream (improve(1), ?), guesses.tail.tail will be Stream(improve(improve(1)), ?) and so on.
The value of guesses is not substituted. A stream is like a list, but its elements are evaluated only when they are needed and then they stored, so next time you access them the evaluation will not be necessary. The reference to the stream itself does not change.
On top of the example Αλεχει wrote, there is a nice explanation in Scala API:
http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Stream
You can easily find out what's going on by modifying the map function, as described in the scaladoc example:
scala> def sqrtStream(x: Double): Stream[Double] = {
| def improve(guess: Double): Double = (guess + x / guess) / 2
| lazy val guesses: Stream[Double] = 1 #:: (guesses map {n =>
| println(n, improve(n))
| improve(n)
| })
| guesses
| }
sqrtStream: (x: Double)Stream[Double]
The output is:
scala> sqrtStream(4).take(10).toList
(1.0,2.5)
(2.5,2.05)
(2.05,2.000609756097561)
(2.000609756097561,2.0000000929222947)
(2.0000000929222947,2.000000000000002)
(2.000000000000002,2.0)
(2.0,2.0)
(2.0,2.0)
(2.0,2.0)
res0: List[Double] = List(1.0, 2.5, 2.05, 2.000609756097561, 2.0000000929222947, 2.000000000000002, 2.0, 2.0, 2.0, 2.0)
println("What is the current number of seconds since midnight?")
val s = readInt
val m = (s/60) % 60
val h = (s/60/60) % 24
That is my current code. I just do not know how to println("") so it displays in hh:mm form. Thank you in advance for any help!
I think the answer is
"%02d:%02d".format(h, m)
based on http://www.scala-lang.org/old/node/5153
Mostly like #Floris said:
val s = System.currentTimeMillis / 1000
val m = (s/60) % 60
val h = (s/60/60) % 24
val str = "%02d:%02d".format(h, m)
// str = 22:40
Now you could print it, just like you would with regular string.
Since scala 2.10 there is string interpolation feature, which allows you to write things like:
val foo = "bar"
println(s"I'm $foo!")
// I'm bar!
But I don't think it is much readable (reminds perl):
val str = f"$h%02d:$m%02d"
// show elapsed time as hours:mins:seconds
val t1 = System.currentTimeMillis/1000
// ... run some code
val t2 = System.currentTimeMillis/1000
var elapsed_s = (t2 - t1)
// for testing invent some time: 4 hours: 20 minutes: 10 seconds
elapsed_s=4*60*60 + 20*60 + 10
val residual_s = elapsed_s % 60
val residual_m = (elapsed_s/60) % 60
val elapsed_h = (elapsed_s/60/60)
// display hours as absolute, minutes & seconds as residuals
println("Elapsed time: " + "%02d:%02d:%02d".format(elapsed_h, residual_m,
residual_s))
I am new to Scala and functional programming.
I was solving problem where you have to read number, and then that number of integers. After that you should calculate sum of all digits in all the integers.
Here is my code
def sumDigits(line: String) =
line.foldLeft(0)(_ + _.toInt - '0'.toInt)
def main(args: Array[String]) {
val numberOfLines = Console.readInt
val lines = for (i <- 1 to numberOfLines) yield Console.readLine
println(lines.foldLeft(0)( _ + sumDigits(_)))
}
Is there more elegant or efficient way?
sumDigits() can be implemented easier with sum:
def sumDigits(line: String) = line.map(_.asDigit).sum
Second foldLeft() can also be replaced with sum:
lines.map(sumDigits).sum
Which brings us to the final version (notice there is no main, instead with extend App):
object Main extends App {
def sumDigits(line: String) = line.map(_.asDigit).sum
val lines = for (_ <- 1 to Console.readInt) yield Console.readLine
println(lines.map(sumDigits).sum)
}
Or if you really want to squeeze as much as possible in one line, inline sumDigits (not recommended):
lines.map(_.map(_.asDigit).sum).sum
I like compact code, so I might (if I was really going for brevity)
object Reads extends App {
import Console._
println( Seq.fill(readInt){readLine.map(_ - '0').sum}.sum )
}
which sets the number of lines inline and does the processing as you go. No error checking, though. You could throw in a .filter(_.isDigit) right after the readLine to at least discard non-digits. You might also def p[A](a: A) = { println(a); a } and wrap the reads in p so you can see what had been typed (by default on some platforms at least there's no echo to screen).
One-liner Answer:
Iterator.continually(Console.readLine).take(Console.readInt).toList.flatten.map(_.asDigit).sum
To start with, you have to do some kind of parsing on line to break apart the existing decimal integers sub-strings:
val numbers = "5 1 4 9 16 25"
val ints = numbers.split("\\s+").toList.map(_.toInt)
Then you want to pull off the first one as the count and keep the rest to decode and sum:
val count :: numbers = ints
Then use the built-in sum method:
val sum = numbers.sum
Altogether in the REPL:
scala> val numbers = "5 1 4 9 16 25"
numbers: String = 5 1 4 9 16 25
scala> val ints = numbers.split("\\s+").toList.map(_.toInt)
ints: List[Int] = List(5, 1, 4, 9, 16, 25)
scala> val count :: numbers = ints
count: Int = 5
numbers: List[Int] = List(1, 4, 9, 16, 25)
scala> val sum = numbers.sum
sum: Int = 55
If you want to do something with the leading number count, you could verify that it's correct:
scala> assert(count == numbers.length)
Which produces no output, since the assertion passes.
If there is any way to call a def from a block
def factor (n: Int) : Int = if (n == 0 ) 1 else n * factor(n-1)
val i = 1000
i.toString.foreach ( x => sum += factor(x.toInt) )
at the end I want to get the sum of factorial of every digit
But it seems like def doesn't return a value, everytime is 0
How to fix it?
Thanks!
The problem actually has nothing to do with Scala per se; your code and your def are fine. The issue is with toInt:
scala> '3'.toInt
res7: Int = 51
toInt doesn't actually convert it as a decimal digit, but as a unicode (ish?) character value. These are producing very large numbers which go beyond what factor can handle:
scala> factor(6)
res8: Int = 720
scala> factor(20)
res9: Int = -2102132736
scala> factor(100)
res10: Int = 0
So instead use (thanks to Luigi)
x.asDigit