Scala, interesting Puzzle with Implicits - scala

here is an interesting puzzle that I can not solve for a few days.
A class takes a function and gives out a string. Main thing is that it puts parentheses when a priority of an argument becomes negative. The goal is to find such a relationship of value, literal and operation, that the parentheses will be at initial place
Known is that:
literal * variable is e.g 2X and not 2 * X
Priority of X (or any other variable) is 5
Priority of 42 (e.g 42.lit or 4.lit * 2.lit which one is unknown) is 4
Priority of X * Y * 2 is 3
Priority of -X * Y * 3 is 1
object Main {
trait Expr[T] {
def literalInt(value: Int): T
def variable(name: String): T
def times(x: T, y: T): T
def plus(x: T, y: T): T
def minus(x: T, y: T): T = plus(x, negate(y))
def negate(x: T): T = times(x, literalInt(-1))
}
object exprSyntax {
def literalInt[T](value: Int)(implicit expr: Expr[T]): T = expr.literalInt(value)
def X[T](implicit expr: Expr[T]): T = expr.variable("x")
def Y[T](implicit expr: Expr[T]): T = expr.variable("y")
def Z[T](implicit expr: Expr[T]): T = expr.variable("z")
implicit class IntToExpr[T](x: Int)(implicit expr: Expr[T]) {
def lit: T = expr.literalInt(x)
}
implicit class NumOps[T](val x: T) extends AnyVal {
def +(y: T)(implicit expr: Expr[T]): T = expr.plus(x, y)
def -(y: T)(implicit expr: Expr[T]): T = expr.minus(x, y)
def *(y: T)(implicit expr: Expr[T]): T = expr.times(x, y)
def unary_-(implicit expr: Expr[T]): T = expr.negate(x)
}
}
final case class Print(s: String, priority: Int, isLit: Boolean = false) {
def print(outer: Int = 0) = if (outer <= priority) s else s"($s)"
}
// interesting starts from here
object Expr {
implicit val stringOrderExpr: Expr[Print] = new Expr[Print] {
override def literalInt(value: Int): Print = Print(value.toString, priority = ???, isLit = true)
override def variable(name: String): Print = Print(name.toUpperCase, priority = ???)
override def times(x: Print, y: Print): Print = {
if (x.isLit){
val print = Print(s"${x.s}${y.s}", priority = ???).print()
Print(print, priority = ???)
}
else {
val print = Print(s"${x.s}*${y.s}", priority = ???).print()
Print(print, priority = ???)
}
}
override def plus(x: Print, y: Print): Print = {
val print = Print(s"${x.s}+${y.s}".toUpperCase, priority = ???).print()
Print(print, y.priority - x.priority)
}
override def minus(x: Print, y: Print): Print = {
val print = Print(s"${x.s}-${y.s}", priority = ???).print()
Print(print, priority = ???)
}
override def negate(x: Print): Print = {
val print = Print(s"-${x.s}", priority = ???).print()
Print(print, priority = ???)
}
}
}
def main(args: Array[String]): Unit = {
import Main.exprSyntax._
def function[T: Main.Expr]: T = X * X + 2.lit * (Y + Z * X * 2.lit) - 7.lit * Z + 4.lit
println(function[Main.Print].priority) // X*X+2(Y+Z*X*2)-7Z+4
}
}

Related

Cannot create constructor with logic in Scala program?

I have the following program:
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
def this(n: Int) = this(n, 1)
def this(s: String) = {
val regex: Regex = "^([+-]?(\\d+|\\d*\\.?\\d+)|\\d*\\/?\\d+)$".r
if (!regex.matches(s)) throw new NumberFormatException()
val input: Array[String] = s.split("\\.|\\/")
val num: Int = input(0).toInt
if (input.length equals 1)
this(num, 1) // problem here
else
this(num, input(1).toInt) // problem here
}
}
I tried to create the constructor with some logic. However, I cannot due to
'Rational' does not take parameters
What's the problem?
Try to introduce a helper method
import scala.util.matching.Regex
def gcd(i: Int, i1: Int): Int = BigInt(i).gcd(BigInt(i1)).toInt
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
def this(n: Int) = this(n, 1)
def this(s: String) = {
this(Rational.transformStr(s)._1, Rational.transformStr(s)._2)
}
}
object Rational {
// helper method
def transformStr(s: String): (Int, Int) = {
val regex: Regex = "^([+-]?(\\d+|\\d*\\.?\\d+)|\\d*\\/?\\d+)$".r
if (!regex.matches(s)) throw new NumberFormatException()
val input: Array[String] = s.split("\\.|\\/")
val num: Int = input(0).toInt
if (input.length equals 1)
(num, 1)
else
(num, input(1).toInt)
}
}
or better, factory methods (because constructors have many limitations)
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
}
object Rational {
// factory methods
def apply(n: Int) = new Rational(n, 1)
def apply(s: String): Rational = {
val regex: Regex = "^([+-]?(\\d+|\\d*\\.?\\d+)|\\d*\\/?\\d+)$".r
if (!regex.matches(s)) throw new NumberFormatException()
val input: Array[String] = s.split("\\.|\\/")
val num: Int = input(0).toInt
if (input.length equals 1)
new Rational(num, 1)
else
new Rational(num, input(1).toInt)
}
}
Executing code in overloaded constructor prior to calling this()
By the way, you can also use default values
class Rational(n: Int, d: Int = 1 /*default*/ ) {
// ...
}
object Rational {
def apply(s: String): Rational = ???
}

Scala: overloaded method value converged with alternatives:

I am still new to Scala (still learning it). I have the following assignment, but am having problems running it due to the error "overloaded method value converged with alternatives:"
Full Error:
\KMeans.scala:101:8: overloaded method value converged with alternatives:
(eta: Double,oldMeans: scala.collection.parallel.ParSeq[kmeans.Point],newMeans: scala.collection.parallel.ParSeq[kmeans.Point])Boolean <and>
(eta: Double,oldMeans: scala.collection.Seq[kmeans.Point],newMeans: scala.collection.Seq[kmeans.Point])Boolean
cannot be applied to (Double)
if (!converged(eta)(means, newMeans))
Can you please help?
The full class is:
package kmeans
import scala.annotation.tailrec
import scala.collection.{Map, Seq, mutable}
import scala.collection.parallel.CollectionConverters._
import scala.collection.parallel.{ParMap, ParSeq}
import scala.util.Random
import org.scalameter._
class KMeans extends KMeansInterface {
def generatePoints(k: Int, num: Int): Seq[Point] = {
val randx = new Random(1)
val randy = new Random(3)
val randz = new Random(5)
(0 until num)
.map({ i =>
val x = ((i + 1) % k) * 1.0 / k + randx.nextDouble() * 0.5
val y = ((i + 5) % k) * 1.0 / k + randy.nextDouble() * 0.5
val z = ((i + 7) % k) * 1.0 / k + randz.nextDouble() * 0.5
new Point(x, y, z)
}).to(mutable.ArrayBuffer)
}
def initializeMeans(k: Int, points: Seq[Point]): Seq[Point] = {
val rand = new Random(7)
(0 until k).map(_ => points(rand.nextInt(points.length))).to(mutable.ArrayBuffer)
}
def findClosest(p: Point, means: IterableOnce[Point]): Point = {
val it = means.iterator
assert(it.nonEmpty)
var closest = it.next()
var minDistance = p.squareDistance(closest)
while (it.hasNext) {
val point = it.next()
val distance = p.squareDistance(point)
if (distance < minDistance) {
minDistance = distance
closest = point
}
}
closest
}
def classify(points: Seq[Point], means: Seq[Point]): Map[Point, Seq[Point]] = {
means.map{(_, Seq())}.toMap ++ points.groupBy(findClosest(_, means))
}
def classify(points: ParSeq[Point], means: ParSeq[Point]): ParMap[Point, ParSeq[Point]] = {
means.map{(_, ParSeq())}.toMap ++ points.groupBy(findClosest(_, means))
}
def findAverage(oldMean: Point, points: Seq[Point]): Point = if (points.isEmpty) oldMean else {
var x = 0.0
var y = 0.0
var z = 0.0
points.foreach { p =>
x += p.x
y += p.y
z += p.z
}
new Point(x / points.length, y / points.length, z / points.length)
}
def findAverage(oldMean: Point, points: ParSeq[Point]): Point = if (points.isEmpty) oldMean else {
var x = 0.0
var y = 0.0
var z = 0.0
points.seq.foreach { p =>
x += p.x
y += p.y
z += p.z
}
new Point(x / points.length, y / points.length, z / points.length)
}
def update(classified: Map[Point, Seq[Point]], oldMeans: Seq[Point]): Seq[Point] = {
oldMeans.par.map(oldMean => findAverage(oldMean, classified(oldMean)))
}
def update(classified: ParMap[Point, ParSeq[Point]], oldMeans: ParSeq[Point]): ParSeq[Point] = {
oldMeans.par.map(oldMean => findAverage(oldMean, classified(oldMean)))
}
def converged(eta: Double, oldMeans: Seq[Point], newMeans: Seq[Point]): Boolean = {
(oldMeans zip newMeans)
.forall(entry => entry._1.squareDistance(entry._2) <= eta)
}
def converged(eta: Double, oldMeans: ParSeq[Point], newMeans: ParSeq[Point]): Boolean = {
(oldMeans zip newMeans)
.forall(entry => entry._1.squareDistance(entry._2) <= eta)
}
#tailrec
final def kMeans(points: Seq[Point], means: Seq[Point], eta: Double): Seq[Point] = {
val meansClassification = classify(points, means)
val newMeans = update(meansClassification, means)
if (!converged(eta)(means, newMeans))
kMeans(points, newMeans, eta)
else
newMeans
}
#tailrec
final def kMeans(points: ParSeq[Point], means: ParSeq[Point], eta: Double): ParSeq[Point] = {
val meansClassification = classify(points, means)
val newMeans = update(meansClassification, means)
if (!converged(eta)(means, newMeans))
kMeans(points, newMeans, eta)
else
newMeans
}
}
/** Describes one point in three-dimensional space.
*
* Note: deliberately uses reference equality.
*/
class Point(val x: Double, val y: Double, val z: Double) {
private def square(v: Double): Double = v * v
def squareDistance(that: Point): Double = {
square(that.x - x) + square(that.y - y) + square(that.z - z)
}
private def round(v: Double): Double = (v * 100).toInt / 100.0
override def toString = s"(${round(x)}, ${round(y)}, ${round(z)})"
}
object KMeansRunner {
val standardConfig = config(
Key.exec.minWarmupRuns -> 20,
Key.exec.maxWarmupRuns -> 40,
Key.exec.benchRuns -> 25,
Key.verbose -> true
) withWarmer(new Warmer.Default)
def main(args: Array[String]): Unit = {
val kMeans = new KMeans()
val numPoints = 500000
val eta = 0.01
val k = 32
val points = kMeans.generatePoints(k, numPoints)
val means = kMeans.initializeMeans(k, points)
val seqtime = standardConfig measure {
kMeans.kMeans(points, means, eta)
}
val parPoints = points.par
val parMeans = means.par
val partime = standardConfig measure {
kMeans.kMeans(parPoints, parMeans, eta)
}
// Additional `println` to avoid bad interaction with JLine output
println()
println()
println()
println()
println(s"sequential time: $seqtime")
println(s"parallel time: $partime")
println(s"speedup: ${seqtime.value / partime.value}")
println()
println()
println()
}
// Workaround Dotty's handling of the existential type KeyValue
implicit def keyValueCoerce[T](kv: (Key[T], T)): KeyValue = {
kv.asInstanceOf[KeyValue]
}
}
The interface:
package kmeans
import scala.collection.{Map, Seq}
import scala.collection.parallel.{ParMap, ParSeq}
/**
* The interface used by the grading infrastructure. Do not change signatures
* or your submission will fail with a NoSuchMethodError.
*/
trait KMeansInterface {
def classify(points: Seq[Point], means: Seq[Point]): Map[Point, Seq[Point]]
def classify(points: ParSeq[Point], means: ParSeq[Point]): ParMap[Point, ParSeq[Point]]
def update(classified: Map[Point, Seq[Point]], oldMeans: Seq[Point]): Seq[Point]
def update(classified: ParMap[Point, ParSeq[Point]], oldMeans: ParSeq[Point]): ParSeq[Point]
def converged(eta: Double, oldMeans: Seq[Point], newMeans: Seq[Point]): Boolean
def converged(eta: Double, oldMeans: ParSeq[Point], newMeans: ParSeq[Point]): Boolean
def kMeans(points: Seq[Point], means: Seq[Point], eta: Double): Seq[Point]
def kMeans(points: ParSeq[Point], means: ParSeq[Point], eta: Double): ParSeq[Point]
}
The method should be called as converged(eta, means, newMeans) not converged(eta)(means, newMeans). If you look, both def converged are defined with a single parameter list (with 3 parameters), not with two.
The most relevant part of this error is not the part you quoted but
cannot be applied to (Double)

Two implicit definitions with same name for a method

I have two implicit declarations that "redefine" x as an operator:
import scala.io.StdIn._
import util._
import scala.language.postfixOps
case class Rectangle(width: Int, height: Int)
case class Circle(ratio: Integer)
case class Cylinder[T](ratio: T, height: T)
object implicitsExample1 {
implicit class RectangleMaker(width: Int) {
def x(height: Int) = Rectangle(width, height)
}
implicit class CircleMaker(ratio: Int) {
def c = Circle(ratio)
}
implicit class CylinderMaker[T](ratio: T) {
def x(height: T) = Cylinder(ratio, height)
}
def main(args: Array[String]) {
val myRectangle = 3 x 4
val myCircle = 3 c
val myCylinder = 4 x 5
println("myRectangle = " + myRectangle)
println("myCircle = " + myCircle)
println("myCylinder = " + myCylinder)
}
}
Here my output gives:
myRectangle = Rectangle(3,4)
myCircle = Circle(3)
myCylinder = Rectangle(4,5)
What I need to do to have something like:
myCylinder = Cylinder[Int](4,5)
I understand that the chosen implicit conversion is the first one declared but is there a way to specify the use of the Cylinder one?
Try combining RectangleMaker and CylinderMaker into a single ShapeMaker implicit class like so
implicit class ShapeMaker[T](width: T) {
def x(height: T)(implicit ev: T =:= Int) = Rectangle(width, height)
def x(height: T) = Cylinder[T](width, height)
}
and provide type ascriptions to value definitions like so
val myRectangle: Rectangle = 3 x 4
val myCircle = 3 c
val myCylinder: Cylinder[Int] = 4 x 5
which outputs
myRectangle = Rectangle(3,4)
myCircle = Circle(3)
myCylinder = Cylinder(4,5)

Using a double value in a Fractional[T] method

I have the following function which generates a Uniform distributed value between 2 bounds:
def Uniform(x: Bounded[Double], n: Int): Bounded[Double] = {
val y: Double = (x.upper - x.lower) * scala.util.Random.nextDouble() + x.lower
Bounded(y, x.bounds)
}
and Bounded is defined as follows:
trait Bounded[T] {
val underlying: T
val bounds: (T, T)
def lower: T = bounds._1
def upper: T = bounds._2
override def toString = underlying.toString + " <- [" + lower.toString + "," + upper.toString + "]"
}
object Bounded {
def apply[T : Numeric](x: T, _bounds: (T, T)): Bounded[T] = new Bounded[T] {
override val underlying: T = x
override val bounds: (T, T) = _bounds
}
}
However, I want Uniform to work on all Fractional[T] values so I wanted to add a context bound:
def Uniform[T : Fractional](x: Bounded[T], n: Int): Bounded[T] = {
import Numeric.Implicits._
val y: T = (x.upper - x.lower) * scala.util.Random.nextDouble().asInstanceOf[T] + x.lower
Bounded(y, x.bounds)
}
This works swell when doing a Uniform[Double](x: Bounded[Double]), but the other ones are impossible and get a ClassCastException at runtime because they can not be casted. Is there a way to solve this?
I'd suggest defining a new type class that characterizes types that you can get random instances of:
import scala.util.Random
trait GetRandom[A] {
def next(): A
}
object GetRandom {
def instance[A](a: => A): GetRandom[A] = new GetRandom[A] {
def next(): A = a
}
implicit val doubleRandom: GetRandom[Double] = instance(Random.nextDouble())
implicit val floatRandom: GetRandom[Float] = instance(Random.nextFloat())
// Define any other instances here
}
Now you can write Uniform like this:
def Uniform[T: Fractional: GetRandom](x: Bounded[T], n: Int): Bounded[T] = {
import Numeric.Implicits._
val y: T = (x.upper - x.lower) * implicitly[GetRandom[T]].next() + x.lower
Bounded(y, x.bounds)
}
And use it like this:
scala> Uniform[Double](Bounded(2, (0, 4)), 1)
res15: Bounded[Double] = 1.5325899033654382 <- [0.0,4.0]
scala> Uniform[Float](Bounded(2, (0, 4)), 1)
res16: Bounded[Float] = 0.06786823 <- [0.0,4.0]
There are libraries like rng that provide a similar type class for you, but they tend to be focused on purely functional ways to work with random numbers, so if you want something simpler you're probably best off writing your own.

How to create custom assignment operator in Scala

I'm trying to create a custom data type that behaves like an Int, but has certain specific behavior and typing (eg., it has to be positive, it has to fit within the range of our database's 'integer' type, etc).
To make it a friendly class, I want to have custom assignment operators, etc., for instance I'd like the following to all work:
val g: GPID = 1 // create a GPID type with value 1
val g: GPID = 1L // take assignment from a Long (and downcast into Int)
if (g == 1) ... // test the value of GPID type against an Int(1)
This is what I have so far but I'm not getting the expected behavior:
case class GPID(value: Int) extends MappedTo[Int] {
require(value >= 1, "GPID must be a positive number")
require(value <= GPDataTypes.integer._2, s"GPID upper bound is ${GPDataTypes.integer._2}")
def this(l: Long) = this(l.toInt)
def GPID = value
def GPID_=(i: Int) = new GPID(i)
def GPID_=(l: Long) = new GPID(l.toInt)
override def toString: String = value.toString
override def hashCode:Int = value
override def equals(that: Any): Boolean =
that match {
case that: Int => this.hashCode == that.hashCode
case that: Long => this.hashCode == that.hashCode
case _ => false
}
}
object GPID {
implicit val writesGPID = new Writes[GPID] {
def writes(g: GPID): JsValue = {
Json.obj(
"GPID" -> g.value
)
}
}
implicit val reads: Reads[GPID] = (
(__ \ "GPID").read[GPID]
)
def apply(l: Long) = new GPID(l.toInt)
implicit def gpid2int(g: GPID): Int = hashCode
implicit def gpid2long(g: GPID): Long = hashCode.toLong
}
The problems I have are:
Assignment doesn't work, for instance:
val g: GPID = 1
Implicit conversion is not working, for instance:
val i: Int = g
Any help would be appreciated... haven't build a custom type like this before so overriding assignment and implicit conversion is new to me...
object TestInt extends App {
class GPID(val value: Int) {
require(value >= 1, "GPID must be a positive number")
require(value <= 10, s"GPID upper bound is 10")
override def equals(that: Any) = value.equals(that)
override def toString = value.toString
// add more methods here (pimp my library)
}
implicit def fromInt(value: Int) = new GPID(value)
implicit def fromInt(value: Long) = new GPID(value.toInt) //possible loss of precision
val g: GPID = 1
val g2: GPID = 1L
if (g == 1)
println("ONE: " + g)
else
println("NOT ONE: " + g)
}
Prints:
ONE: 1