Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SCALA:生成满足某些条件的Tuple2对象列表_Scala - Fatal编程技术网

SCALA:生成满足某些条件的Tuple2对象列表

SCALA:生成满足某些条件的Tuple2对象列表,scala,Scala,我想生成Tuple2对象的列表。列表中的每个元组(a,b)都应该满足以下条件:a和b都是完美的正方形,(b/30)N(N甚至可以是一个BigInt) 我正在尝试编写一个scala函数来生成满足上述要求的元组列表? 这是我的尝试..它对int和long很好..但对于BigInt,我面临的是sqrt问题..以下是我的编码方法: scala> def genTups(N:Long) ={ | val x = for(s<- 1L to Math.sqrt(N).toLong)

我想生成
Tuple2对象的
列表
。列表中的每个元组
(a,b)
都应该满足以下条件:
a
b
都是完美的正方形,
(b/30)N
N
甚至可以是一个
BigInt
) 我正在尝试编写一个
scala函数
来生成满足上述要求的
元组列表
? 这是我的尝试..它对int和long很好..但对于BigInt,我面临的是sqrt问题..以下是我的编码方法:

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))
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 }
      val x = for(s<- sqt(N1) to sqt(N2)) 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)
  }
scala>def genTups(N:Long)={
|val x=对于(s(a,b)}.toList
|y.过滤器(t=>(t._1*30/t._2)>=1)
| }
genTups:(N:Long)列表[(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))
使用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))
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 }
      val x = for(s<- sqt(N1) to sqt(N2)) 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)
  }
def-genTups(N1:BigInt,N2:BigInt)={
def sqt(n:BigInt):BigInt={
变量a=BigInt(1)
变量b=(n>>5)+BigInt(8)
而((b-a)>=0){
变量mid:BigInt=(a+b)>>1
如果(mid*mid-n>0)b=mid-1
否则a=mid+1
};a-1}
val x=对于(s(a,b)}.toList
y、 过滤器(t=>(t._1*30/t._2)>=1)
}

非常感谢您对改进算法的帮助。

首先创建一个函数来检查数字是否为完美平方

def squareRootOfPerfectSquare(a: Int): Option[Int] = {
  val sqrt = math.sqrt(a)
  if (sqrt % 1 == 0)
    Some(sqrt.toInt)
  else
    None
}
然后,创建另一个func,它将根据上述条件计算这个元组列表

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

希望有帮助!!!

通过将计算
x
的方式更改为以下方式,您可以避免算法中的
sqrt

  val x = (BigInt(1) to N).map(x => x*x).takeWhile(_ <= N)
valx=(BigInt(1)到N)。map(x=>x*x)。takeWhile(x*x)。takeWhile(while(a,b)}.toList
y、 过滤器(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(N:BigInt)=
(BigInt(1)到N)
.map(x=>x*x)
.takeWhile(u(a,b)}
.过滤器(t=>(t._1*30/t._2)>=1)
托利斯先生

为了追求性能,我提出了这个递归版本,它看起来要快得多

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
}
def-genTups(N1:BigInt,N2:BigInt)={
def sqt(n:BigInt):BigInt={
变量a=BigInt(1)
变量b=(n>>5)+BigInt(8)
而((b-a)>=0){
变量mid:BigInt=(a+b)>>1
如果(中间*中间-n>0){
b=中间-1
}否则{
a=mid+1
}
}
a-1
}
@泰勒克
def循环(a:BigInt,rem:List[BigInt],res:List[(BigInt,BigInt)]):List[(BigInt,BigInt)]=
快速眼动匹配{
案例Nil=>res
案例头部::尾部=>
val a30=a*30
val thisRes=rem.takeWhile(uz(a,b))
循环(头部、尾部、thisRes.reverse::res)
}
val squares=(sqt(N1)到sqt(N2)).map(s=>s*s.toList
环(方头,方头,方尾,零)。反转
}

循环的每次递归都会为给定的
a
值添加所有匹配对。结果是反向生成的,因为添加到长列表的前面要比添加到尾部快得多。

到目前为止您尝试了什么?您遇到了什么问题?展示您的尝试,您将获得关于如何改进它的建议,但不要像以前那样k个人为你完成作业。你不需要
case
子句中的条件,因为
组合
保持值的有序性,
a
总是
是。刚才我也意识到了这一点。如果我删除它,它能提高性能一点吗?是的,但我刚刚添加了一个更快的实现,你可能想要这是一个很小但非常有用的提示。避免向我询问BigInt的适当sqrt函数。谢谢Tim。在研究了你的建议后,我发现了关于两种方法性能的另一个问题。在我的方法中,我只是计算从1到sqrt(N)的平方只有,但在这种方法中,我们从1到N计算,并使用
takeWhile()
过滤计算出的平方,其中N可能比sqrt(N)大得多。你对此有什么要澄清的吗?@Raghhuramm这可能是更大数字的性能杀手,因为组合方法将是计算密集型的。你可以通过将
.view
放在
.map
之前,并将
Vector
更改为
Seq
,来改进性能,但如果你想获得更好的性能,你可能需要需要一个更好的算法。这里有没有比使用组合法更好的方法?我想你错过了
generateTuple
的代码,而是放了两份
squareRootOfPerfectSquare
的副本…@Tim谢谢你指出。我想知道为什么我的答案一直没有被接受。无论如何,谢谢!!!还有,问题on要求提供
BigInt
的解决方案,因此您不能使用
sqrt
:(