本节介绍 R 的基础语法,也是使用 R 必须掌握的常识性基础知识。

多亏了强大的数据科学 IDE RStudio,有很多与分析工作无关的繁琐细节已经不需要关注了,我们可以更专注于数据的处理和分析,因此本节尝试用简短的篇幅来介绍 R 作为一门编程语言的基础语法,而后用最快的速度转向其作为数据科学分析工具的功能(毕竟 R 是一门数据科学语言)。

对象和函数

R 的大多数功能都是通过对对象(object)的创建和操作(manipulation)以及使用各种函数来实现的。抛开计算机科学的严格定义,对象实际上是指一切可以进行赋值(assign)的东西。R 是一门面向对象编程的语言,因此任何内容都可以是对象,例如变量、函数、数据、图表等等。

变量的创建和删除

R 通过赋值语句来创建变量。与其他编程语言不同,R 的标准赋值号并不是=,而是<-或者->,“箭头”方向指向被赋值的变量。尽管大多数情况下=也是允许的,但这种用法不标准,有些情况下还可能造成问题。在 RStudio 中的 R 环境下,可以通过快捷键 “Alt + -” 来快速插入<-

x <- 2
y <- 5

而如果将赋值语句用小括号括起来,则会在赋值后返回该变量的值:

(x <- 3)
[1] 3

删除变量使用rm()函数,如果需要清空环境中的所有变量,可以直接点击 RStudio 右上角环境窗口的扫帚图标。

函数的使用和创建

R 函数的使用语法和许多其他编程语言一样,都是函数名(对象,参数)的形式,视函数定义情况可能没有对象,传递实参的方法也分为位置参数和关键字参数,当传递的实参和定义中的相应形参所处位置相同时,可以省略参数名,否则就需要显式地指出参数名。使用?函数名或者help(函数名)可以在帮助文档中查看一个函数使用的各种参数的详细信息。

使用包名::函数名()可以在不加载包的前提下调用某个包中的函数(同样的语法也可以用来调用某个包中的数据集)。

R 函数的创建使用function()函数,其基本结构为:

函数名 = function(形式变量,形式参数) {
       各种运算、操作
       ……
       return(返回值)
}

返回值不是必须的,但大多数函数都有。

R 还支持匿名函数,也就是不显式地使用函数名,也不必显式地使用return语句,而使用function(变量){……, 变量表达式}的方式,把最后一个表达式的结果作为返回值。在实际调用时,将定义语句括起来,再在后面将要传递的变量值括起来: (function(变量){变量表达式})(变量值)。当只有一个表达式的时候,花括号可以省略。此外,匿名函数也可以通过赋值来指定函数名,从而成为普通的函数。

基本数学运算和函数

R 作为一门数据科学语言,当然离不开计算,base 包中包含了一些基本的数学运算,如下表所示:

运算 符号/函数 运算 符号/函数 运算 符号/函数 运算 符号/函数
+ - * /
乘方 ^ %/% 余数/取模 %% 自然对数 log()
常用对数(十进对数) log10() 以a为底b的对数 log(x=b, base=a) 以e为底的指数 exp() 绝对值 abs()
算术平方根 sqrt() 正弦 sin() 余弦 cos() 正切 tan()
余切 atan() 正割 acos() 余割 asin() 双曲正弦 sinh()
双曲余弦 cosh() 双曲正切 tanh()

此外,对于小数:

计算精度的设置使用函数options(digits = 位数, prompt = "光标类型"),最高精度为16位;

对于取整,R 提供了一系列取整函数:

  • floor() 向下取整

  • ceiling() 向上取整

  • trunc() 截去小数部分取整(向0取整)

  • round(x, digits = )signif(x, digits = ) 均为四舍五入,前者 digits 参数设定小数点后保留位数,默认取 0,后者 digits 参数设定保留有效数字位数,默认取 6

浮点数比较问题

由于计算机以二进制储存数据,因此在计算十进制浮点数时,可能无法得到精确的结果,例如,在R和Python中:

0.2 + 0.2 == 0.4会返回True,但0.1 + 0.2 == 0.3就会返回False,因为0.1无法以二进制精确表示。

对于这一问题,在 R 中可以使用all.equal()函数来进行比较,该函数包含一个绝对误差限参数tolerance,忽略小于该值的误差, 默认值为1.5×10−8。在 Python 中可以用math包中的isclose()函数或者numpy包中的allclose()函数来进行比较。

条件与循环

条件语句和循环语句在任何编程语言中都十分重要,对代码的结构有较大影响。

条件语句

和许多编程语言一样,R 使用 if 条件语句,

基本 if 语句:if(逻辑值条件) {操作} 满足条件时执行操作。R 对缩进不敏感,只要操作的内容在条件之后即可,可以是同一行,也可以是下一行,当只有一个操作语句时,甚至可以不加花括号。

if-else 语句:if(条件1) {操作1} else {操作2} 满足条件1时执行操作1,否则执行操作2。if-else 语句相当于在基本 if 语句之后增加了一个分支条件,else 语句不能单独存在,也不能单独占一行,必须跟操作1的右花括号在同一行,或者在操作1只有一个操作语句时,与操作1语句在同一行。

else if 语句:if(条件1) {操作1} else if(条件2) {操作2} ··· else 之后可以插入 if 语句,成为 else if 语句,进一步增加分支条件(注意 else if 是一个整体不能分行),后面还可以继续增加 else 语句和 else if 语句,来增加更多的分支。

示例:使用 if 条件语句自定义一个绝对值函数.

ABS <- function(x) {
  if (x>=0) {
    answer <- x
    } else answer <- -x
  return(answer)
}
ABS(12);ABS(-6)

循环语句

R 有三种循环语句:for 循环语句、while 循环语句和 repeat 循环语句。

for 循环语句

当明确循环次数或者需要遍历的值的范围时,使用 for 循环语句,其语法为:

for (循环变量 in 向量) {操作} 循环变量会遍历向量中的每一个值,每次循环都会进行相应的操作。

示例:计算数列 \(a_n = \dfrac1n\) 的前100项和.

Sum = 0
for (i in 1:100) {
  Sum = Sum + 1/i
}
Sum
[1] 5.187378

while 循环语句

当循环次数未知,也没有明确的遍历值范围,只知道需要在什么条件下进行循环时,使用 while 循环语句,其语法为:

while (循环条件) {操作} 只要循环条件满足,就会进行一次循环,执行一次操作,然后再检验条件是否满足。由于没有显式地指明循环次数,因此要注意避免死循环。

示例:找出1000以内最大的19的倍数.

ind <- 0
while (ind<=1000) {
  if (ind%%19==0) ans <- ind
  ind <- ind + 1
}
ans
[1] 988

repeat 循环语句

当 for 循环语句和 while 循环语句的使用条件都不满足时,要使用循环只能使用 repeat 循环语句,其语法为:

repeat {操作} 这是一个无限执行的死循环,想要结束循环需要使用以下方式来打断:

  • break:退出循环
  • next:跳过本次循环
  • stop()函数:退出循环并以报错的形式显示指定信息

这些方法也可用于另外两种循环。

示例:在循环中增加一个用于判断的 if 语句,如果循环次数超过100,就退出循环.

ind = 0
while(1>0){
  x = 1
  ind = ind + 1
  if (ind>=100) break
}
ind
[1] 100
LS0tDQp0aXRsZTogIlIg5Z+656GA6K+t5rOVIg0KYXV0aG9yOiAiRWxsZXJ5IEhvbG1lcyINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIHRvYzogeWVzDQogICAgIyB0b2NfZmxvYXQ6IHllcw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGV2YWw9VFJVRSkNCmBgYA0KDQrmnKzoioLku4vnu40gUiDnmoTln7rnoYDor63ms5XvvIzkuZ/mmK/kvb/nlKggUiDlv4Xpobvmjozmj6HnmoTluLjor4bmgKfln7rnoYDnn6Xor4bjgIINCg0K5aSa5LqP5LqG5by65aSn55qE5pWw5o2u56eR5a2mIElERSBSU3R1ZGlv77yM5pyJ5b6I5aSa5LiO5YiG5p6Q5bel5L2c5peg5YWz55qE57mB55CQ57uG6IqC5bey57uP5LiN6ZyA6KaB5YWz5rOo5LqG77yM5oiR5Lus5Y+v5Lul5pu05LiT5rOo5LqO5pWw5o2u55qE5aSE55CG5ZKM5YiG5p6Q77yM5Zug5q2k5pys6IqC5bCd6K+V55So566A55+t55qE56+H5bmF5p2l5LuL57uNIFIg5L2c5Li65LiA6Zeo57yW56iL6K+t6KiA55qE5Z+656GA6K+t5rOV77yM6ICM5ZCO55So5pyA5b+r55qE6YCf5bqm6L2s5ZCR5YW25L2c5Li65pWw5o2u56eR5a2m5YiG5p6Q5bel5YW355qE5Yqf6IO977yI5q+V56ufIFIg5piv5LiA6Zeo5pWw5o2u56eR5a2m6K+t6KiA77yJ44CCDQoNCiMg5a+56LGh5ZKM5Ye95pWwDQoNClIg55qE5aSn5aSa5pWw5Yqf6IO96YO95piv6YCa6L+H5a+55a+56LGhKG9iamVjdCnnmoTliJvlu7rlkozmk43kvZwobWFuaXB1bGF0aW9uKeS7peWPiuS9v+eUqOWQhOenjeWHveaVsOadpeWunueOsOeahOOAguaKm+W8gOiuoeeul+acuuenkeWtpueahOS4peagvOWumuS5ie+8jOWvueixoeWunumZheS4iuaYr+aMh+S4gOWIh+WPr+S7pei/m+ihjOi1i+WAvChhc3NpZ24p55qE5Lic6KW/44CCUiDmmK/kuIDpl6jpnaLlkJHlr7nosaHnvJbnqIvnmoTor63oqIDvvIzlm6DmraTku7vkvZXlhoXlrrnpg73lj6/ku6XmmK/lr7nosaHvvIzkvovlpoLlj5jph4/jgIHlh73mlbDjgIHmlbDmja7jgIHlm77ooajnrYnnrYnjgIINCg0KIyMg5Y+Y6YeP55qE5Yib5bu65ZKM5Yig6ZmkDQoNClIg6YCa6L+H6LWL5YC86K+t5Y+l5p2l5Yib5bu65Y+Y6YeP44CC5LiO5YW25LuW57yW56iL6K+t6KiA5LiN5ZCM77yMUiDnmoTmoIflh4botYvlgLzlj7flubbkuI3mmK9gPWDvvIzogIzmmK9gPC1g5oiW6ICFYC0+YO+8jCLnrq3lpLQi5pa55ZCR5oyH5ZCR6KKr6LWL5YC855qE5Y+Y6YeP44CC5bC9566h5aSn5aSa5pWw5oOF5Ya15LiLYD1g5Lmf5piv5YWB6K6455qE77yM5L2G6L+Z56eN55So5rOV5LiN5qCH5YeG77yM5pyJ5Lqb5oOF5Ya15LiL6L+Y5Y+v6IO96YCg5oiQ6Zeu6aKY44CC5ZyoIFJTdHVkaW8g5Lit55qEIFIg546v5aKD5LiL77yM5Y+v5Lul6YCa6L+H5b+r5o236ZSuICJBbHQgKyAtIiDmnaXlv6vpgJ/mj5LlhaVgPC1g44CCDQoNCmBgYHtyfQ0KeCA8LSAyDQp5IDwtIDUNCmBgYA0KDQrogIzlpoLmnpzlsIbotYvlgLzor63lj6XnlKjlsI/mi6zlj7fmi6zotbfmnaXvvIzliJnkvJrlnKjotYvlgLzlkI7ov5Tlm57or6Xlj5jph4/nmoTlgLzvvJoNCg0KYGBge3J9DQooeCA8LSAzKQ0KYGBgDQoNCuWIoOmZpOWPmOmHj+S9v+eUqGBybSgpYOWHveaVsO+8jOWmguaenOmcgOimgea4heepuueOr+Wig+S4reeahOaJgOacieWPmOmHj++8jOWPr+S7peebtOaOpeeCueWHuyBSU3R1ZGlvIOWPs+S4iuinkueOr+Wig+eql+WPo+eahOaJq+W4muWbvuagh+OAgg0KDQojIyDlh73mlbDnmoTkvb/nlKjlkozliJvlu7oNCg0KUiDlh73mlbDnmoTkvb/nlKjor63ms5XlkozorrjlpJrlhbbku5bnvJbnqIvor63oqIDkuIDmoLfvvIzpg73mmK9g5Ye95pWw5ZCNKOWvueixoSzlj4LmlbApYOeahOW9ouW8j++8jOinhuWHveaVsOWumuS5ieaDheWGteWPr+iDveayoeacieWvueixoe+8jOS8oOmAkuWunuWPgueahOaWueazleS5n+WIhuS4uuS9jee9ruWPguaVsOWSjOWFs+mUruWtl+WPguaVsO+8jOW9k+S8oOmAkueahOWunuWPguWSjOWumuS5ieS4reeahOebuOW6lOW9ouWPguaJgOWkhOS9jee9ruebuOWQjOaXtu+8jOWPr+S7peecgeeVpeWPguaVsOWQje+8jOWQpuWImeWwsemcgOimgeaYvuW8j+WcsOaMh+WHuuWPguaVsOWQjeOAguS9v+eUqGA/5Ye95pWw5ZCNYOaIluiAhWBoZWxwKOWHveaVsOWQjSlg5Y+v5Lul5Zyo5biu5Yqp5paH5qGj5Lit5p+l55yL5LiA5Liq5Ye95pWw5L2/55So55qE5ZCE56eN5Y+C5pWw55qE6K+m57uG5L+h5oGv44CCDQoNCuS9v+eUqGDljIXlkI06OuWHveaVsOWQjSgpYOWPr+S7peWcqOS4jeWKoOi9veWMheeahOWJjeaPkOS4i+iwg+eUqOafkOS4quWMheS4reeahOWHveaVsO+8iOWQjOagt+eahOivreazleS5n+WPr+S7peeUqOadpeiwg+eUqOafkOS4quWMheS4reeahOaVsOaNrumbhu+8ieOAgg0KDQpSIOWHveaVsOeahOWIm+W7uuS9v+eUqGBmdW5jdGlvbigpYOWHveaVsO+8jOWFtuWfuuacrOe7k+aehOS4uu+8mg0KDQpgYGAgICAgICAgICANCuWHveaVsOWQjSA9IGZ1bmN0aW9uKOW9ouW8j+WPmOmHj++8jOW9ouW8j+WPguaVsCkgew0KICAgICAgIOWQhOenjei/kOeul+OAgeaTjeS9nA0KICAgICAgIOKApuKApg0KICAgICAgIHJldHVybijov5Tlm57lgLwpDQp9DQpgYGANCg0K6L+U5Zue5YC85LiN5piv5b+F6aG755qE77yM5L2G5aSn5aSa5pWw5Ye95pWw6YO95pyJ44CCDQoNClIg6L+Y5pSv5oyBPGZvbnQgY29sb3IgPSByZWQ+5Yy/5ZCN5Ye95pWwPC9mb250Pu+8jOS5n+WwseaYr+S4jeaYvuW8j+WcsOS9v+eUqOWHveaVsOWQje+8jOS5n+S4jeW/heaYvuW8j+WcsOS9v+eUqGByZXR1cm5g6K+t5Y+l77yM6ICM5L2/55SoYGZ1bmN0aW9uKOWPmOmHjyl74oCm4oCmLCDlj5jph4/ooajovr7lvI99YOeahOaWueW8j++8jOaKiuacgOWQjuS4gOS4quihqOi+vuW8j+eahOe7k+aenOS9nOS4uui/lOWbnuWAvOOAguWcqOWunumZheiwg+eUqOaXtu+8jOWwhuWumuS5ieivreWPpeaLrOi1t+adpe+8jOWGjeWcqOWQjumdouWwhuimgeS8oOmAkueahOWPmOmHj+WAvOaLrOi1t+adpe+8miBgKGZ1bmN0aW9uKOWPmOmHjyl75Y+Y6YeP6KGo6L6+5byPfSko5Y+Y6YeP5YC8KWDjgILlvZPlj6rmnInkuIDkuKrooajovr7lvI/nmoTml7blgJnvvIzoirHmi6zlj7flj6/ku6XnnIHnlaXjgILmraTlpJbvvIzljL/lkI3lh73mlbDkuZ/lj6/ku6XpgJrov4fotYvlgLzmnaXmjIflrprlh73mlbDlkI3vvIzku47ogIzmiJDkuLrmma7pgJrnmoTlh73mlbDjgIINCg0KIyMg5Z+65pys5pWw5a2m6L+Q566X5ZKM5Ye95pWwDQoNClIg5L2c5Li65LiA6Zeo5pWw5o2u56eR5a2m6K+t6KiA77yM5b2T54S256a75LiN5byA6K6h566X77yMYmFzZSDljIXkuK3ljIXlkKvkuobkuIDkupvln7rmnKznmoTmlbDlrabov5DnrpfvvIzlpoLkuIvooajmiYDnpLrvvJoNCg0KfCAgICAgICAg6L+Q566XICAgICAgICB8IOespuWPty/lh73mlbAgfCAgICAgIOi/kOeulyAgICAgIHwgICAg56ym5Y+3L+WHveaVsCAgICAgfCAgICAg6L+Q566XICAgICAgfCDnrKblj7cv5Ye95pWwIHwgICDov5DnrpcgICB8IOespuWPty/lh73mlbAgfA0KfDotLS0tLS0tOnw6LS0tLS0tLTp8Oi0tLS0tLS06fDotLS0tLS0tOnw6LS0tLS0tLTp8Oi0tLS0tLS06fDotLS0tLS0tOnw6LS0tLS0tLTp8DQp8ICAgICAgICAg5YqgICAgICAgICAgfCAgICBcKyAgICAgfCAgICAgICDlh48gICAgICAgfCAgICAgICAgXC0gICAgICAgIHwgICAgICDkuZggICAgICAgfCAgICBcKiAgICAgfCAgICDpmaQgICAgfCAgICAgLyAgICAgfA0KfCAgICAgICAg5LmY5pa5ICAgICAgICB8ICAgIFxeICAgICB8ICAgICAgIOWVhiAgICAgICB8ICAgICAgICUvJSAgICAgICAgfCAgIOS9meaVsC/lj5bmqKEgICB8ICAgICUlICAgICB8IOiHqueEtuWvueaVsCB8ICAgbG9nKCkgICB8DQp8IOW4uOeUqOWvueaVsCjljYHov5vlr7nmlbApIHwgIGxvZzEwKCkgIHwg5LulYeS4uuW6lWLnmoTlr7nmlbAgfCBsb2coeD1iLCBiYXNlPWEpIHwg5LulZeS4uuW6leeahOaMh+aVsCB8ICAgZXhwKCkgICB8ICDnu53lr7nlgLwgIHwgICBhYnMoKSAgIHwNCnwgICAgIOeul+acr+W5s+aWueaguSAgICAgfCAgc3FydCgpICAgfCAgICAgIOato+W8piAgICAgIHwgICAgICBzaW4oKSAgICAgICB8ICAgICDkvZnlvKYgICAgICB8ICAgY29zKCkgICB8ICAg5q2j5YiHICAgfCAgIHRhbigpICAgfA0KfCAgICAgICAg5L2Z5YiHICAgICAgICB8ICBhdGFuKCkgICB8ICAgICAg5q2j5YmyICAgICAgfCAgICAgIGFjb3MoKSAgICAgIHwgICAgIOS9meWJsiAgICAgIHwgIGFzaW4oKSAgIHwg5Y+M5puy5q2j5bymIHwgIHNpbmgoKSAgIHwNCnwgICAgICDlj4zmm7LkvZnlvKYgICAgICB8ICBjb3NoKCkgICB8ICAgIOWPjOabsuato+WIhyAgICB8ICAgICAgdGFuaCgpICAgICAgfCAgICAgICAgICAgICAgIHwgICAgICAgICAgIHwgICAgICAgICAgfCAgICAgICAgICAgfA0KDQrmraTlpJbvvIzlr7nkuo7lsI/mlbDvvJoNCg0K6K6h566X57K+5bqm55qE6K6+572u5L2/55So5Ye95pWwYG9wdGlvbnMoZGlnaXRzID0g5L2N5pWwLCBwcm9tcHQgPSAi5YWJ5qCH57G75Z6LIilg77yM5pyA6auY57K+5bqm5Li6MTbkvY3vvJsNCg0K5a+55LqO5Y+W5pW077yMUiDmj5DkvpvkuobkuIDns7vliJflj5bmlbTlh73mlbDvvJoNCg0KLSAgIGBmbG9vcigpYCDlkJHkuIvlj5bmlbQNCg0KLSAgIGBjZWlsaW5nKClgIOWQkeS4iuWPluaVtA0KDQotICAgYHRydW5jKClgIOaIquWOu+Wwj+aVsOmDqOWIhuWPluaVtO+8iOWQkTDlj5bmlbTvvIkNCg0KLSAgIGByb3VuZCh4LCBkaWdpdHMgPSApYCDlkowgYHNpZ25pZih4LCBkaWdpdHMgPSApYCDlnYfkuLrlm5voiI3kupTlhaXvvIzliY3ogIUgZGlnaXRzIOWPguaVsOiuvuWumuWwj+aVsOeCueWQjuS/neeVmeS9jeaVsO+8jOm7mOiupOWPliAw77yM5ZCO6ICFIGRpZ2l0cyDlj4LmlbDorr7lrprkv53nlZnmnInmlYjmlbDlrZfkvY3mlbDvvIzpu5jorqTlj5YgNg0KDQojIyMgKio8Zm9udCBjb2xvciA9IHJlZD7mta7ngrnmlbDmr5TovoPpl67popg8L2ZvbnQ+KioNCg0K55Sx5LqO6K6h566X5py65Lul5LqM6L+b5Yi25YKo5a2Y5pWw5o2u77yM5Zug5q2k5Zyo6K6h566X5Y2B6L+b5Yi25rWu54K55pWw5pe277yM5Y+v6IO95peg5rOV5b6X5Yiw57K+56Gu55qE57uT5p6c77yM5L6L5aaC77yM5ZyoUuWSjFB5dGhvbuS4re+8mg0KDQpgMC4yICsgMC4yID09IDAuNGDkvJrov5Tlm55gVHJ1ZWDvvIzkvYZgMC4xICsgMC4yID09IDAuM2DlsLHkvJrov5Tlm55gRmFsc2Vg77yM5Zug5Li6MC4x5peg5rOV5Lul5LqM6L+b5Yi257K+56Gu6KGo56S644CCDQoNCuWvueS6jui/meS4gOmXrumimO+8jOWcqCBSIOS4reWPr+S7peS9v+eUqGBhbGwuZXF1YWwoKWDlh73mlbDmnaXov5vooYzmr5TovoPvvIzor6Xlh73mlbDljIXlkKvkuIDkuKrnu53lr7nor6/lt67pmZDlj4LmlbBgdG9sZXJhbmNlYO+8jOW/veeVpeWwj+S6juivpeWAvOeahOivr+W3ru+8jCDpu5jorqTlgLzkuLoxLjXDlzEwXuKIkjhe44CC5ZyoIFB5dGhvbiDkuK3lj6/ku6XnlKhgbWF0aGDljIXkuK3nmoRgaXNjbG9zZSgpYOWHveaVsOaIluiAhWBudW1weWDljIXkuK3nmoRgYWxsY2xvc2UoKWDlh73mlbDmnaXov5vooYzmr5TovoPjgIINCg0KIyDmnaHku7bkuI7lvqrnjq8NCg0K5p2h5Lu26K+t5Y+l5ZKM5b6q546v6K+t5Y+l5Zyo5Lu75L2V57yW56iL6K+t6KiA5Lit6YO95Y2B5YiG6YeN6KaB77yM5a+55Luj56CB55qE57uT5p6E5pyJ6L6D5aSn5b2x5ZON44CCDQoNCiMjIOadoeS7tuivreWPpQ0KDQrlkozorrjlpJrnvJbnqIvor63oqIDkuIDmoLfvvIxSIOS9v+eUqCBpZiDmnaHku7bor63lj6XvvIwNCg0K5Z+65pysIGlmIOivreWPpe+8mmBpZijpgLvovpHlgLzmnaHku7YpIHvmk43kvZx9YCDmu6HotrPmnaHku7bml7bmiafooYzmk43kvZzjgIJSIOWvuee8qei/m+S4jeaVj+aEn++8jOWPquimgeaTjeS9nOeahOWGheWuueWcqOadoeS7tuS5i+WQjuWNs+WPr++8jOWPr+S7peaYr+WQjOS4gOihjO+8jOS5n+WPr+S7peaYr+S4i+S4gOihjO+8jOW9k+WPquacieS4gOS4quaTjeS9nOivreWPpeaXtu+8jOeUmuiHs+WPr+S7peS4jeWKoOiKseaLrOWPt+OAgg0KDQppZi1lbHNlIOivreWPpe+8mmBpZijmnaHku7YxKSB75pON5L2cMX0gZWxzZSB75pON5L2cMn1gIOa7oei2s+adoeS7tjHml7bmiafooYzmk43kvZwx77yM5ZCm5YiZ5omn6KGM5pON5L2cMuOAgmlmLWVsc2Ug6K+t5Y+l55u45b2T5LqO5Zyo5Z+65pysIGlmIOivreWPpeS5i+WQjuWinuWKoOS6huS4gOS4quWIhuaUr+adoeS7tu+8jGVsc2Ug6K+t5Y+l5LiN6IO95Y2V54us5a2Y5Zyo77yM5Lmf5LiN6IO95Y2V54us5Y2g5LiA6KGM77yM5b+F6aG76Lef5pON5L2cMeeahOWPs+iKseaLrOWPt+WcqOWQjOS4gOihjO+8jOaIluiAheWcqOaTjeS9nDHlj6rmnInkuIDkuKrmk43kvZzor63lj6Xml7bvvIzkuI7mk43kvZwx6K+t5Y+l5Zyo5ZCM5LiA6KGM44CCDQoNCmVsc2UgaWYg6K+t5Y+l77yaYGlmKOadoeS7tjEpIHvmk43kvZwxfSBlbHNlIGlmKOadoeS7tjIpIHvmk43kvZwyfSDCt8K3wrdgIGVsc2Ug5LmL5ZCO5Y+v5Lul5o+S5YWlIGlmIOivreWPpe+8jOaIkOS4uiBlbHNlIGlmIOivreWPpe+8jOi/m+S4gOatpeWinuWKoOWIhuaUr+adoeS7tu+8iOazqOaEjyBlbHNlIGlmIOaYr+S4gOS4quaVtOS9k+S4jeiDveWIhuihjO+8ie+8jOWQjumdoui/mOWPr+S7pee7p+e7reWinuWKoCBlbHNlIOivreWPpeWSjCBlbHNlIGlmIOivreWPpe+8jOadpeWinuWKoOabtOWkmueahOWIhuaUr+OAgg0KDQrnpLrkvovvvJrkvb/nlKggaWYg5p2h5Lu26K+t5Y+l6Ieq5a6a5LmJ5LiA5Liq57ud5a+55YC85Ye95pWwLg0KDQpgYGB7cn0NCkFCUyA8LSBmdW5jdGlvbih4KSB7DQogIGlmICh4Pj0wKSB7DQogICAgYW5zd2VyIDwtIHgNCiAgICB9IGVsc2UgYW5zd2VyIDwtIC14DQogIHJldHVybihhbnN3ZXIpDQp9DQpBQlMoMTIpO0FCUygtNikNCmBgYA0KDQojIyDlvqrnjq/or63lj6UNCg0KUiDmnInkuInnp43lvqrnjq/or63lj6XvvJpmb3Ig5b6q546v6K+t5Y+l44CBd2hpbGUg5b6q546v6K+t5Y+l5ZKMIHJlcGVhdCDlvqrnjq/or63lj6XjgIINCg0KIyMjIGZvciDlvqrnjq/or63lj6UNCg0K5b2T5piO56Gu5b6q546v5qyh5pWw5oiW6ICF6ZyA6KaB6YGN5Y6G55qE5YC855qE6IyD5Zu05pe277yM5L2/55SoIGZvciDlvqrnjq/or63lj6XvvIzlhbbor63ms5XkuLrvvJoNCg0KYGZvciAo5b6q546v5Y+Y6YePIGluIOWQkemHjykge+aTjeS9nH1gIOW+queOr+WPmOmHj+S8mumBjeWOhuWQkemHj+S4reeahOavj+S4gOS4quWAvO+8jOavj+asoeW+queOr+mDveS8mui/m+ihjOebuOW6lOeahOaTjeS9nOOAgg0KDQrnpLrkvovvvJrorqHnrpfmlbDliJcgJGFfbiA9IFxkZnJhYzFuJCDnmoTliY0xMDDpobnlkowuDQpgYGB7cn0NClN1bSA8LSAwDQpmb3IgKGkgaW4gMToxMDApIHsNCiAgU3VtIDwtIFN1bSArIDEvaQ0KfQ0KU3VtDQpgYGANCg0KDQojIyMgd2hpbGUg5b6q546v6K+t5Y+lDQoNCuW9k+W+queOr+asoeaVsOacquefpe+8jOS5n+ayoeacieaYjuehrueahOmBjeWOhuWAvOiMg+WbtO+8jOWPquefpemBk+mcgOimgeWcqOS7gOS5iOadoeS7tuS4i+i/m+ihjOW+queOr+aXtu+8jOS9v+eUqCB3aGlsZSDlvqrnjq/or63lj6XvvIzlhbbor63ms5XkuLrvvJoNCg0KYHdoaWxlICjlvqrnjq/mnaHku7YpIHvmk43kvZx9YCDlj6ropoHlvqrnjq/mnaHku7bmu6HotrPvvIzlsLHkvJrov5vooYzkuIDmrKHlvqrnjq/vvIzmiafooYzkuIDmrKHmk43kvZzvvIznhLblkI7lho3mo4DpqozmnaHku7bmmK/lkKbmu6HotrPjgILnlLHkuo7msqHmnInmmL7lvI/lnLDmjIfmmI7lvqrnjq/mrKHmlbDvvIzlm6DmraTopoHms6jmhI/pgb/lhY3mrbvlvqrnjq/jgIINCg0K56S65L6L77ya5om+5Ye6MTAwMOS7peWGheacgOWkp+eahDE555qE5YCN5pWwLg0KDQpgYGB7cn0NCmluZCA8LSAwICPlrprkuYnkuIDkuKrmjIfnpLrlj5jph4/orrDlvZXlvqrnjq/mrKHmlbANCndoaWxlIChpbmQ8PTEwMDApIHsNCiAgaWYgKGluZCUlMTk9PTApIGFucyA8LSBpbmQNCiAgaW5kIDwtIGluZCArIDENCn0NCmFucw0KYGBgDQojIyMgcmVwZWF0IOW+queOr+ivreWPpQ0KDQrlvZMgZm9yIOW+queOr+ivreWPpeWSjCB3aGlsZSDlvqrnjq/or63lj6XnmoTkvb/nlKjmnaHku7bpg73kuI3mu6HotrPml7bvvIzopoHkvb/nlKjlvqrnjq/lj6rog73kvb/nlKggcmVwZWF0IOW+queOr+ivreWPpe+8jOWFtuivreazleS4uu+8mg0KDQpgcmVwZWF0IHvmk43kvZx9YCDov5nmmK/kuIDkuKrml6DpmZDmiafooYznmoTmrbvlvqrnjq/vvIzmg7PopoHnu5PmnZ/lvqrnjq/pnIDopoHkvb/nlKjku6XkuIvmlrnlvI/mnaXmiZPmlq3vvJoNCg0KLSBgYnJlYWtg77ya6YCA5Ye65b6q546vDQotIGBuZXh0YO+8mui3s+i/h+acrOasoeW+queOrw0KLSBgc3RvcCgpYOWHveaVsO+8mumAgOWHuuW+queOr+W5tuS7peaKpemUmeeahOW9ouW8j+aYvuekuuaMh+WumuS/oeaBrw0KDQrov5nkupvmlrnms5XkuZ/lj6/nlKjkuo7lj6blpJbkuKTnp43lvqrnjq/jgIINCg0K56S65L6L77ya5Zyo5b6q546v5Lit5aKe5Yqg5LiA5Liq55So5LqO5Yik5pat55qEIGlmIOivreWPpe+8jOWmguaenOW+queOr+asoeaVsOi2hei/hzEwMO+8jOWwsemAgOWHuuW+queOry4NCg0KYGBge3J9DQppbmQgPSAwICPlrprkuYnkuIDkuKrmjIfnpLrlj5jph4/orrDlvZXlvqrnjq/mrKHmlbANCndoaWxlKDE+MCl7DQogIHggPSAxDQogIGluZCA9IGluZCArIDENCiAgaWYgKGluZD49MTAwKSBicmVhaw0KfQ0KaW5kDQpgYGA=