用汉字标注十万个“对不起”

知乎上有个非常有趣的问题

“男友让我打十万个「对不起」,汉字标上多少遍。”这个问题用 R 如何实现?

关键是“汉字标上多少遍”。还有“对不起”必须是中文的。

source here

回答里解答方法五花八门,可惜,要么不是用规定的语言,要么就是程序有bug无法实现。
今天太阳高照,我的番茄种子发了大芽,于是心情一好,就用R把它实现了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
saySorry <- function() {
## 这里用来规定单位,除了个位不需要标注,其他的按顺序标记好
unit <- c("", "十", "百", "千", "万", "十万")
## 这个用来标记数字0-9,因为0在R中无法提取vector里的位数,所以这里只用到了1-9
digit <- c("壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖")
## 初始化要输出的结果向量
result <- c()
## 不是要十万吗?那就循环好了,i表示第“i”遍。有人可能会问,为什么不用sapply?额,我觉得单纯的循环操作,for比较快一些。如果你有兴趣,也可以用sapply,但是肯定要改写一部分代码
for(i in 1:1.1e4) {
### 取得i的长度
n <- nchar(i)
### 初始化“遍数”
count <- ""
### 循环,“遍数”有长就循环几次
for (j in 1:n) {
### 从1开始遍历“遍数”之长,求得结果是当前“遍数”的当前位数上的值
t <- as.numeric(substr(i, j, j))
### 判断,以求“零”的情况
if (t==0 && j!=1) {
num <- "零"
} else num <- paste0(digit[t], unit[n-j+1])
count <- paste0(count, num)
}
### 去掉开头的
count <- gsub("^壹十", "十", count)
### 去掉重复的
while (grepl("零零", count)) count <- gsub("零零", "零", count)
### 去掉末尾的
count <- gsub("零$", "", count)
result[i] <- paste0("对不起! 第", count, "遍……")
}
result
}

这个循环在三位、四位数的时候还是秒算的,十万毕竟基数比较大,所以计算用了大约一分半的时间。

1
2
3
4
> system.time(result <- saySorry())
user system elapsed
76.844 1.455 78.907
> writeLines(result, 'iAmSoSorryQAQ.txt')

随机抽查20个:

  • 对不起! 第柒万壹千叁百零陆遍……
  • 对不起! 第伍千玖百贰十壹遍……
  • 对不起! 第玖万叁千壹百捌十玖遍……
  • 对不起! 第肆千伍百柒十叁遍……
  • 对不起! 第贰万叁千玖百叁十肆遍……
  • 对不起! 第伍万陆千零陆十陆遍……
  • 对不起! 第陆万柒千捌百捌十陆遍……
  • 对不起! 第伍万柒千零陆十玖遍……
  • 对不起! 第柒万零叁百捌十捌遍……
  • 对不起! 第伍万贰千零玖十捌遍……
  • 对不起! 第伍万零柒百零贰遍……
  • 对不起! 第柒万叁千叁百零玖遍……
  • 对不起! 第伍万捌千陆百叁十壹遍……
  • 对不起! 第壹万玖千叁百肆十贰遍……
  • 对不起! 第肆万壹千捌百贰十壹遍……
  • 对不起! 第壹万玖千零陆十壹遍……
  • 对不起! 第贰万肆千柒百零叁遍……
  • 对不起! 第伍千肆百壹十伍遍……
  • 对不起! 第叁万零玖百伍十陆遍……
  • 对不起! 第捌万伍千柒百玖十伍遍……

结果还是令人满意的!LOL!

0%