在scala中生成给定字符串的所有IP地址
我在尝试写一个给定一串数字的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
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)