Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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
Kotlin ASCII艺术练习,但我不理解这个解决方案_Kotlin_Fold_Ascii Art - Fatal编程技术网

Kotlin ASCII艺术练习,但我不理解这个解决方案

Kotlin ASCII艺术练习,但我不理解这个解决方案,kotlin,fold,ascii-art,Kotlin,Fold,Ascii Art,我正在做代码命名练习,我成功地完成了ASCII艺术题,它既长又难,但我做到了。 现在我读了其中一个解决方案,它是用5行代码完成的! 我试图理解它,但我没有做到这一点,有人能帮我一步一步的解释吗 该测试为您提供以下输入: 第1行:ASCII艺术中表示的字母的宽度L。所有字母的宽度都相同 第2行:ASCII艺术中表示的字母的高度H。所有字母的高度都相同 第3行:文本T的行,由N个ASCII字符组成 以下行:字符串ABCDEFGHIJKLMNOPQRSTUVWXYZ?用ASCII艺术表示 这是解决方案

我正在做代码命名练习,我成功地完成了ASCII艺术题,它既长又难,但我做到了。 现在我读了其中一个解决方案,它是用5行代码完成的! 我试图理解它,但我没有做到这一点,有人能帮我一步一步的解释吗

该测试为您提供以下输入:

第1行:ASCII艺术中表示的字母的宽度L。所有字母的宽度都相同

第2行:ASCII艺术中表示的字母的高度H。所有字母的高度都相同

第3行:文本T的行,由N个ASCII字符组成

以下行:字符串ABCDEFGHIJKLMNOPQRSTUVWXYZ?用ASCII艺术表示

这是解决方案之一:

fun main(args : Array<String>) {
    val L = readLine()!!.toInt()
    val H = readLine()!!.toInt()
    val T = readLine()!!.toUpperCase().replace("[^A-Z]".toRegex(), "[")

    val rows = (0 until H).map{readLine()!!}

    (0 until H).map{h -> T.fold(""){ a, c -> a + rows[h].substring((c-'A')*L, (c-'A')*L+L) }}.forEach{println(it)}
}
我将非常感谢您的帮助:


另外,我不确定什么是.fold和.map。

让我们逐行分析

val L = readLine()!!.toInt()
读取一个Int并将其放入变量L

读取另一个Int并将其放入变量H中

读取字符串,将其所有字母转换为大写字符,使a变为a,用[character]替换任何非字母的字符[^a-Z]语法来自RegEx,而不是Kotlin,并放入变量T

创建一个从0到H-1的数字列表,对于每个数字,将其转换为用户提供的字符串映射函数将T1类型的列表转换为T2类型的列表;在这种情况下,它将由0到H创建的Int类型的列表转换为字符串列表,这是readLine!!的结果。将列表放入变量行中。

创建一个包含从0到H-1的数字的列表,并将每个数字H转换为字符串

在解释这个字符串是如何创建的之前,让我们先分析一下折叠中发生了什么

当调用fold时,fold receiver,即在.之前的变量是一个字符串,因为变量T是一个字符串

有两个参数,a和c,其中a是一个与接收器类型相同的字符串,c是一个字符,因为字符串是字符的集合。我们只能在集合中使用折叠,这样做时,第一个参数将是其接收器的相同类型,第二个参数将是其接收器元素的相同类型

有一个隐式返回,它是与变量行的H元素的子串连接的参数,因为行是一个列表,如上所述,这个列表的任何元素都是一个字符串;也可以考虑这个列表的第一个元素在这个列表的零个位置,等等,和B的符号x[i]。作为列表x的第i个元素;这就是Kotlin管理列表访问的方式

这个子字符串从位置c-'A'*L开始,在位置c-'A'*L+L结束。要理解它,把字符看作一个数字。所以,当你写'A'时,实际上你写的是65。这是一个命名为ASCII的约定。所以当你写'A'-'A'时,你做的是65-65,这是0。对于'B'-'A',这意味着66-65,因为'B'是一个位置aheaASCII中A的d,也就是1。因为L也是一个Int,只要把它替换到表达式中,你就会得到一个Int

但这两个参数是什么?a和c?fold只是一个循环。在第一次迭代中,a==调用fold后括号和c==T[0]之间的值,即变量T的第一个字符,它是接收器。在这种情况下,返回一些值,a的值与行[h]的子字符串连接在下一次迭代中,a==和c==T[1]。在下一次迭代中,a==和c==T[2]。循环将重复,直到T的所有元素都被处理

最后,在forEach中,将打印fold创建的每个字符串。如果仍有疑问,只需在屏幕上打印每个变量并尝试理解:

(0 until H).map{ h ->
    println("h=$h")
    T.fold(""){ a, c ->
        println("a=$a, c=$c")
        println("c - 'A' = ${c - 'A'}")
        a + rows[h].substring((c-'A')*L, (c-'A')*L+L)
    }
}
希望你能明白

编辑:我试着把回复放在评论中,但我觉得太长了,所以我做了编辑

为了更好地理解,让我们定义一个函数printscii,它是您的原始函数,但参数是输入。如果您不知道函数是什么,请不要担心

有趣的printascil:Int,H:Int,T:String,rows:List{ 0到H.map{H-> T.fold{a,c-> a+行[h]。子字符串c-'a'*L,c-'a'*L+L } }.forEach{printlnit} } 您可以调用如下函数:

printascil=1,H=2,T=some字符串,rows=listOfstring1,string2 在这种情况下,L将等于1,H将等于2,T将等于一些字符串,行将等于listOfstring1,string2。现在,让我们来玩它:

printascil=1,H=1,T=ABCDE,rows=listo12345//输出为12345 printascil=1,H=1,T=AACDE,rows=listo12345//输出为11345 printascil=1,H=1,T=ABCBA,rows=listo12345//输出为12321 printascil=1,H=1,T=EDCBA,rows=listo12345//输出为54321 printascil=1,H=1,T=AAAAA,rows=listo12345//输出为11111 可以看到T变量定义了h 将打印以下行

现在,让我们把L变量改为2

现在您可以看到字符串T中的字符A与行中字符串中的子字符串12相关,字符串T中的字符B与行中的子字符串34相关,依此类推。当我们将L更改为2时,T中的每个字符都与行中大小为2的子字符串相关。如果需要,可以尝试使用L等于3,但请确保在行的第一个元素中添加5个字符,即字符串T的大小

一般来说,当H等于1时,T中的每个字符都与行的第一个元素的大小为L的子字符串相关,记住这一点!。但是如何计算哪个子字符串属于某个字符呢

注意,

当L==1时,A与从0开始的子串相关,B与从1开始的子串相关,C与从2开始的子串相关,依此类推

当L==2时,A与从0开始的子字符串相关,B与从2开始的子字符串相关,C与从4开始的子字符串相关,依此类推

你能猜出L==3的模式吗?模式很简单:计算某个字母到A的距离。例如,A和B之间的距离是1,A和E之间的距离是4。将该距离乘以L,得到子字符串的起始位置

例如,当L==2时,C与从4开始的子字符串相关。应用我们的方法,C和A之间的距离是2。乘以L,即2,我们得到2*2=4,这是子字符串的起始位置

由于子字符串的大小为L,正如我们在上面发现的,为了得到子字符串的最终位置,我们可以将L添加到起始位置

基于以上信息,我们可以编写Kotlin代码

如何计算某些字符c和“A”之间的距离?回答:c-‘A’

如何获取子字符串的起始位置?回答:c-‘A’*L

如何获取子字符串的结束位置?回答:c-‘A’*L+L

如何从行的第一个元素获取子字符串?答:行[0]。子字符串c-'A'*L,c-'A'*L+L

这是针对H==1的,但是您可以增加它的值并得出相同的结论

对于第二个问题,您可以看一看,特别是否定字符类部分。正则表达式与Kotlin无关,但可以在Kotlin代码中使用正则表达式

简单地说,[^A-Z]在正则表达式中表示匹配不在A和Z之间的单个字符,[^0-9]表示匹配不在0和9之间的单个字符。如果要匹配a和Z之间的单个字符,只需删除插入符号,即[a-Z]


也就是说,.replace[^A-Z].toRegex[意味着匹配一个不在A和Z之间的字符,并将这个字符替换为[。为什么[?记住'B'-'A'==1和'E'-'A'==4?如果你跟随火车,你会看到'Z'-'A'==25。ASCII表格中紧接着'Z'的字符是[,所以'['-'A'==26。正因为如此,任何不在A和Z之间的字符c都将计算表达式c-'A'到26。

非常感谢!这是一个非常长而详细的答案,帮助很大。我理解了大部分内容,有些部分我必须重读10遍才能理解。我将一步一步地尝试打印它,以获得更好的想法。o我唯一还没有得到的部分是c-'A'*L和c-'A'*L+L部分。为什么它要乘以长度?哦,还有,我不理解正则表达式部分,那是什么[^A-Z]是什么意思?如果这是一个基本问题,很抱歉,但我搜索了一点,但变得更混乱。^T是否尝试排除a到Z的字母?这是排除某些内容的唯一方法吗?我已编辑了我的答案,如果您现在明白了,请告诉我。祝您编码愉快!
val T = readLine()!!
    .toUpperCase()
    .replace("[^A-Z]".toRegex(), "[")
val rows = (0 until H).map{ readLine()!! }
(0 until H).map{ h ->
    T.fold(""){ a, c ->
        a + rows[h].substring((c-'A')*L, (c-'A')*L+L)
    }
}
.forEach{ println(it) }
(0 until H).map{ h ->
    println("h=$h")
    T.fold(""){ a, c ->
        println("a=$a, c=$c")
        println("c - 'A' = ${c - 'A'}")
        a + rows[h].substring((c-'A')*L, (c-'A')*L+L)
    }
}
printAscii(L = 2, H = 1, T = "ABCDE", rows = listOf("1234567890")) // the output is 1234567890
printAscii(L = 2, H = 1, T = "AACDE", rows = listOf("1234567890")) // the output is 1212567890
printAscii(L = 2, H = 1, T = "ABCBA", rows = listOf("1234567890")) // the output is 1234563412
printAscii(L = 2, H = 1, T = "EDCBA", rows = listOf("1234567890")) // the output is 9078563412
printAscii(L = 2, H = 1, T = "AAAAA", rows = listOf("1234567890")) // the output is 1212121212