我要生成list
的{{1}}。列表中的每个元组Tuple2 objects
均应满足以下条件:(a,b)
和a
都是完美的平方,b
以及(b/30)<a<b
和a>N
(b>N
甚至可以是N
)
我正在尝试编写BigInt
来生成满足以上要求的scala function
吗?
这是我的尝试。.它对于Ints和Longs来说很好。.但是对于BigInt,我面临着sqrt问题。.这是我的编码方法,如下所示:
the List of Tuples
使用BigInt平方根算法对此进行了改进,如下所示:
scala> def genTups(N:Long) ={
| val x = for(s<- 1L to Math.sqrt(N).toLong) yield s*s;
| val y = x.combinations(2).map{ case Vector(a,b) => (a,b)}.toList
| y.filter(t=> (t._1*30/t._2)>=1)
| }
genTups: (N: Long)List[(Long, Long)]
scala> genTups(30)
res32: List[(Long, Long)] = List((1,4), (1,9), (1,16), (1,25), (4,9), (4,16), (4,25), (9,16), (9,25), (16,25))
我感谢我在算法上的任何改进。
答案 0 :(得分:2)
您可以通过将sqrt
的计算方式更改为以下方式来避免算法中的x
:
val x = (BigInt(1) to N).map(x => x*x).takeWhile(_ <= N)
最后一个函数是:
def genTups(N: BigInt) = {
val x = (BigInt(1) to N).map(x => x*x).takeWhile(_ <= N)
val y = x.combinations(2).map { case Vector(a, b) if (a < b) => (a, b) }.toList
y.filter(t => (t._1 * 30 / t._2) >= 1)
}
您还可以将其重写为如下所示的单个操作链:
def genTups(N: BigInt) =
(BigInt(1) to N)
.map(x => x * x)
.takeWhile(_ <= N)
.combinations(2)
.map { case Vector(a, b) if a < b => (a, b) }
.filter(t => (t._1 * 30 / t._2) >= 1)
.toList
为了追求性能,我想出了这个递归版本,该版本似乎要快得多
def genTups(N1: BigInt, N2: BigInt) = {
def sqt(n: BigInt): BigInt = {
var a = BigInt(1)
var b = (n >> 5) + BigInt(8)
while ((b - a) >= 0) {
var mid: BigInt = (a + b) >> 1
if (mid * mid - n > 0) {
b = mid - 1
} else {
a = mid + 1
}
}
a - 1
}
@tailrec
def loop(a: BigInt, rem: List[BigInt], res: List[(BigInt, BigInt)]): List[(BigInt, BigInt)] =
rem match {
case Nil => res
case head :: tail =>
val a30 = a * 30
val thisRes = rem.takeWhile(_ <= a30).map(b => (a, b))
loop(head, tail, thisRes.reverse ::: res)
}
val squares = (sqt(N1) to sqt(N2)).map(s => s * s).toList
loop(squares.head, squares.tail, Nil).reverse
}
循环的每次递归都会为给定值a
添加所有匹配对。结果是反向生成的,因为添加到长列表的前面比添加到列表的末尾要快得多。
答案 1 :(得分:-1)
首先创建一个函数来检查数字是否为完美正方形。
def squareRootOfPerfectSquare(a: Int): Option[Int] = {
val sqrt = math.sqrt(a)
if (sqrt % 1 == 0)
Some(sqrt.toInt)
else
None
}
然后,创建另一个函数,该函数将根据上述条件计算此元组列表。
def generateTuples(n1:Int,n2:Int)={
for{
b <- 1 to n2;
a <- 1 to n1 if(b>a && squareRootOfPerfectSquare(b).isDefined && squareRootOfPerfectSquare(a).isDefined)
} yield ( (a,b) )
}
然后在使用参数generateTuples(5,10)
调用函数时,您将获得输出
res0: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((1,4), (1,9), (4,9))
希望有帮助!