在scala中生成给定字符串的所有IP地址

在scala中生成给定字符串的所有IP地址,scala,recursion,Scala,Recursion,我在尝试写一个给定一串数字的IP生成器。生成器将接受一个数字字符串作为输入,如“17234”,并将返回所有可能的IP列表,如下所示: 1.7.2.34 1.7.23.4 1.72.3.4 17.2.3.4 def genip(ip:String):Unit = { def legal(ip:String):Boolean = (ip.size == 1) || (ip.size == 2) || (ip.size == 3) def genips(ip:String,porti

我在尝试写一个给定一串数字的IP生成器。生成器将接受一个数字字符串作为输入,如“
17234
”,并将返回所有可能的IP列表,如下所示:

1.7.2.34
1.7.23.4
1.72.3.4
17.2.3.4
def genip(ip:String):Unit = {
    def legal(ip:String):Boolean = (ip.size == 1) || (ip.size == 2) || (ip.size == 3)
    def genips(ip:String,portion:Int,accum:String):Unit = portion match {
        case 1 if legal(ip) => println(accum+ip)
        case _ if portion > 1 => {
            genips(ip.drop(1),portion-1,if(accum.size == 0) ip.take(1)+"." else accum+ip.take(1)+".")
            genips(ip.drop(2),portion-1,if(accum.size == 0) ip.take(2)+"." else accum+ip.take(2)+".")
            genips(ip.drop(3),portion-1,if(accum.size == 0) ip.take(3)+"." else accum+ip.take(3)+".")
        }
        case _ => return
    }
    genips(ip,4,"")
}
我试图编写一个代码段来生成,如下所示:

1.7.2.34
1.7.23.4
1.72.3.4
17.2.3.4
def genip(ip:String):Unit = {
    def legal(ip:String):Boolean = (ip.size == 1) || (ip.size == 2) || (ip.size == 3)
    def genips(ip:String,portion:Int,accum:String):Unit = portion match {
        case 1 if legal(ip) => println(accum+ip)
        case _ if portion > 1 => {
            genips(ip.drop(1),portion-1,if(accum.size == 0) ip.take(1)+"." else accum+ip.take(1)+".")
            genips(ip.drop(2),portion-1,if(accum.size == 0) ip.take(2)+"." else accum+ip.take(2)+".")
            genips(ip.drop(3),portion-1,if(accum.size == 0) ip.take(3)+"." else accum+ip.take(3)+".")
        }
        case _ => return
    }
    genips(ip,4,"")
}
其思想是将该字符串划分为四个八位字节,然后将该八位字节进一步划分为大小分别为“1”、“2”和“3”的字符串,然后递归下降到剩余的字符串中

我不确定我是否走上了正确的道路,但如果有人能建议一种更实用的方法来实现同样的目标,那就太好了


谢谢

以下是附加代码的替代版本:

  def generateIPs(digits : String) : Seq[String] = generateIPs(digits, 4)

  private def generateIPs(digits : String, partsLeft : Int) : Seq[String] = {
    if ( digits.size < partsLeft || digits.size > partsLeft * 3) {
      Nil
    } else if(partsLeft == 1) {
      Seq(digits)
    } else {
      (1 to 3).map(n => generateIPs(digits.drop(n), partsLeft - 1)
        .map(digits.take(n) + "." + _)
      ).flatten
    }
  }

  println("Results:\n" + generateIPs("17234").mkString("\n"))
def generateIPs(数字:字符串):Seq[String]=generateIPs(数字,4)
专用def generateIPs(数字:字符串,partsLeft:Int):Seq[String]={
如果(digits.sizepartsLeft*3){
无
}否则如果(partsLeft==1){
序号(位数)
}否则{
(1到3).map(n=>generateIPs(数字.drop(n),partsLeft-1)
.map(数字。取(n)+“+┱)
).压扁
}
}
println(“结果:\n”+generateIPs(“17234”).mkString(“\n”))
主要变化:

  • 方法现在返回字符串集合(而不是单元),因此它们是适当的函数(而不是副作用),并且易于测试

  • 避免重复相同的代码3次,这取决于我们获取的数字的大小

  • 不将累积的中间结果作为方法参数传递-在这种情况下,它没有意义,因为您最多有4个递归调用,没有它更容易阅读,尽管在许多情况下,当您失去尾部递归时,离开它可能是合理的


注意:最后一个
map
语句是一个很好的候选语句,可以被
替换为
,以理解
,许多开发人员发现这更易于阅读和推理,尽管我将把它留作练习:)

您的代码是正确的想法;我不确定它的功能是否真的有帮助,但我将展示功能性和副作用的方法来实现您想要的。首先,我们需要一个很好的例程来划分一些数字,确保剩余的数据可以划分,并确保它们在IP的范围内:

def validSize(i: Int, len: Int, more: Int) = i + more <= len && i + 3*more >= len
def chunk(s: String, more: Int) = {
  val parts = for (i <- 1 to 3 if validSize(i, s.length, more)) yield s.splitAt(i)
  parts.filter(_._1.toInt < 256)
}
无论哪种方式,逻辑都是一样的。这就是它的工作原理:

scala> genIPs("1238516")
res2: List[String] = List(1.23.85.16, 1.238.5.16, 1.238.51.6,
                          12.3.85.16, 12.38.5.16, 12.38.51.6,
                          123.8.5.16, 123.8.51.6, 123.85.1.6)