首页 > 其他分享 >ARTS_5

ARTS_5

时间:2022-11-15 13:33:35浏览次数:132  
标签:... ARTS return len let closures loop

概述

ARTS 是耗子叔发起的编程挑战:

每周完成一个ARTS: 每周至少做一个 leetcode 的算法题、阅读并点评至少一篇英文技术文章、学习至少一个技术技巧、分享一篇有观点和思考的技术文章。(也就是 Algorithm、Review、Tip、Share 简称ARTS)

Algorithm

正则表达式匹配

说白了就是一道暴搜,直接DFS搜到底就可以。因为看范围也不大,最大递归栈肯定不会超过1e6。

但是细节比较多。

个人采取了比较简单的方式,就是先处理模式串\(pp\),并新开一个标记数组\(f\),如果这个字符是可以任意个数的话就标记为1。

就比如输入的模式串为".*a*a"的话,那么处理完就是\(f:[1, 1, 0]\)和\(pp:['.', 'a', 'a']\)

那么接下来就是DFS的处理了。

最简单的情况就是模式串\(pp\)这一位不是任意的,并且模式串\(pp\)跟匹配串\(s\)这一位相同或者是'.'。

接下来就考虑如果是任意的该怎么办,其实就是从0开始到上限枚举就行了。

其实我们也很容易想出,匹配成功的情况,也就是模式串的当前匹配位跟匹配串的当前匹配位都到了最后,也就是大于等于len。要是一个大于等于而另外一个没有大于等于,那就是false了。

但是还有一个corner case,也就是因为*代表的是任意个,也就是0个也是可以的,所以当匹配串超出的时候,还需要特判模式串后面是不是都是*。

具体看代码:

func Match(s string, i int, p []byte, j int, f []int) bool {
   if j >= len(p) && i >= len(s) {	// 都超出肯定匹配成功
      return true
   }
   if j >= len(p) {
      return false
   }
   if i >= len(s) {	
      for k := j; k < len(p); k++ {	//特判后面是不是都是*
         if f[k] == 0 {
            return false
         }
      }
      return true
   }
   if f[j] == 1 {
      if Match(s, i, p, j+1, f) {	//枚举匹配为0的情况
         return true
      }
      for k := i; k < len(s); k = k + 1 { //枚举匹配为1, 2, 3...的情况
         if p[j] == s[k] || p[j] == '.' {
            if Match(s, k+1, p, j+1, f) {
               return true
            }
         } else {
            return false
         }
      }
   }
   if p[j] == '.' || p[j] == s[i] {
      return Match(s, i+1, p, j+1, f)
   }
   return false
}

func isMatch(s string, p string) bool {
   var (
      f  = make([]int, 0, len(p))
      pp = make([]byte, 0, len(p))
   )

   for j := 0; j < len(p); j++ {	//预处理模式串
      pp = append(pp, p[j])
      if j+1 < len(p) && p[j+1] == '*' {
         f = append(f, 1)
         j++
      } else {
         f = append(f, 0)
      }
   }
   //fmt.Println(f)
   //fmt.Println(string(pp))
   return Match(s, 0, pp, 0, f)
}

Tips

如何通过.bat一键修改与还原DNS地址?

最近要压测线上服务器。但是每次访问线上的Grafana的时候我都要手动修改DNS,之后修改完了就不能访问外网了。每次要找资料又要设置回去,在经历了一个星期的摧残之后,我总算下定决心学习用批处理去修改DNS地址。

(3条消息) 用bat修改IP、网关、DNS_weixin_34212762的博客-CSDN博客

一开始是根据这篇博客找到了算是可行的批处理脚本,之后就开始学习批处理的语句。

https://www.yiibai.com/batch_script/

之后把一开始的那个脚本的语句弄弄懂就开始自己写了。

一开始遇到了几个批处理语句相关的问题:

  1. @是什么作用
  2. > nul是什么意思

有兴趣可以自己找一下...

弄清楚了之后就开始手动写了,观察之前的脚本发现他是通过netsh这个工具去修改的,于是就去网上学习,怎么用netsh去修改DNS。

https://blog.csdn.net/u012206617/article/details/127186324

值得一提的是这个教程是有点错误的,这个参数设置了会报错

image-20221102180009220

写完之后跑发现居然失败了,通过echo打印出执行语句,发现居然是因为中文乱码了(本地连接的名字叫做“以太网”)!?

最后发现是vscode的锅,bat运行的编码模式是ANSI,但是vscode貌似不支持。于是就用记事本来重新写了一遍,并保存为ANSI格式,最后成功运行。

优化:

由于涉及到底层的修改,所以一般跑.bat都需要管理员权限,每次都要右键管理员模式运行舒适麻烦。有没有让.bat自动获取管理员权限的语句呢?跟sudo差不多的

https://www.zhihu.com/question/34541107

%1 start "" mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c ""%~s0"" ::","","runas",1)(window.close)&&exit

学会了吗?赶紧去试试吧!

Review

在看Go的技术文章的时候,偶然间翻到了这位佬的博客https://colobu.com/

再看这篇文章的时候,看到了两个名词不是很理解:per-loop,per-iteration

于是就去谷歌上搜...

就又来到了一个佬的博客里:https://nullprogram.com/blog/2014/06/06/

(我发现歪果仁都很喜欢js跟java)

佬主要是因为JS将per-loop改成了per-iteration所以谈了谈这两个模式。

稍微用我自己的话翻译一下这篇文章:

这篇文章主要是讲ECMA-262 6th中对loop的一些改动。也由此引申出了一个许多编程语言的自古以来的老问题。也就是我们最开始讲的per-loop的问题。

就拿C语言举例:

在K&R C中,

布莱恩·柯林汉(Brian Kernighan) 和 丹尼斯·里奇(Dennis Ritchie) 出版了一本书,名叫《The C Programming Language》,人们称这个版本的 C语言为K&R C

一般的for loop包含以下四个部分,执行顺序按照:

for (INITIALIZATION; CONDITION; ITERATION) {
    BODY;
}
  1. 执行 INITIALIZATION
  2. 执行 CONDITION,为假(false)则退出
  3. 执行BODY
  4. 执行ITERATION
  5. 回到2

C89

在C89中,一般是这么写for-loop的:

int count = 10;
/* ... */
int i;
for (i = 0; i < count; i++) {
    double foo;
    /* ... */
}

也就是变量i需要先定义在loop之外。

C99

在C99中,变成了可以这样写:

int count = 10;
/* ... */
for (int i = 0; i < count; i++) {
    double foo;
    /* ... */
}

那我们考虑一下变量i所属的作用域是在哪个范围?

一般我们学校所学就告诉我们,i所在范围就是在这个for的范围内。

但是实际上for里面还有两层:

for-scope

也就是变量i是处于Loop Scope里,也就是说其实还是在foo的外层。

所以对于foo变量来讲,C99的for-loop实现跟C89的实现其实是一样的。

JavaScript中的let

在js中,没有块作用域的概念,只有函数作用域。在最新的6th edition中,引入了let语句。通过let声明的变量将拥有块作用域。

let count = 10;
// ...
for(let i = 0; i < count; i++) {
    let foo;
    // ...
}
console.log(foo); // error
console.log(i);   // error

闭包陷阱(The Closure Trap)

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。用人话来讲,是一个捕获外部变量,并返回这个外部变量相关的函数(一般)。

上述说的per-loop的情况,在一般的场景里是不会导致出现错误的。但是一旦与闭包相结合之后,就会有问题。因为一般闭包设计都是,当执行到这一个函数的时候才会调用这个变量。

以下是一个Python的例子:

closures = []
for i in xrange(2):
    closures.append(lambda: i)
closures[0]()  # => 1
closures[1]()  # => 1

Perl例子:

my @closures;
for (my $i = 0; $i < 2; $i++) {
    push(@closures, sub { return $i; });
}
$closures[0]();  # => 2
$closures[1]();  # => 2

Ruby也是类似:

closures = []
for i in (0..1)
  closures << lambda { i }
end
closures[0].call  # => 1
closures[1].call  # => 1

当然,解决这些问题的方法也很简单,只需要在iteration scope中建立局部变量就行。

就像在perl里:

my @closures;
for (my $i = 0; $i < 2; $i++) {
    my $value = $i;
    push(@closures, sub { return $value; });
}
$closures[0]();  # => 0
$closures[1]();  # => 1

JavaScript的前后对比

let closures = [];
for (let i = 0; i < 2; i++) {
    closures.push(function() { return i; });
}

/* Before the change: */
closures[0]();  // => 2
closures[1]();  // => 2

/* After the change: */
closures[0]();  // => 0
closures[1]();  // => 1

也就是说在新版的js中,for-loop的作用域划分会变成这样:

for-scope-js

将会更好的服务闭包与for - loop的结合。

总结

作者仍不确定这样的改动是否合适。但是这样的fix确实是更符合程序员的逻辑。然而这个问题的修复,可能会导致之前已经记住这个机制,并且写代码就是为了捕获不变的loop scope变量的话,就会出现问题。也就是说,程序的原本可以通过自己加局部变量变成捕获局部,不加变成捕获外部。现在的话就只能统一捕获局部了。

其他的语言例如C#与Perl也有这样的问题,但是他们的解决方式不是改变for-loop而是推出了一个新的loop叫做for-each的方式来达到同样效果。

作者认为 Python 和 Ruby 的 for ... in 表单应该表现得像这样 foreach。这些可能在早期设计错误,但此时无法更改它们的语义。因为 JavaScript 的 var 从一开始就设计不正确,所以 let 提供了修复 var 的机会。

Share

阿里技术专家详解DDD系列 第四讲 - 领域层设计规范 - 知乎 (zhihu.com)主要是从群友这篇文章里看到了OOP实现,之后又想到了我现在使用的GO感觉并没有很OOP于是就去搜,golang 是面向对象的语言吗? - 知乎 (zhihu.com)。得到了回答,Go可以是也可以不是,更为通用。

之后回答里面提到了两篇教学文章:

Structs Instead of Classes - Object Oriented Programming in Golang (golangbot.com)

Methods, Interfaces and Embedded Types in Go (ardanlabs.com)

也是让人受益匪浅。

标签:...,ARTS,return,len,let,closures,loop
From: https://www.cnblogs.com/Vikyanite/p/16892127.html

相关文章

  • vue+echarts绘制地图
    代码实现importchinaJsonfrom'echarts/map/json/china.json'exportdefault{mounted(){letmyChart=this.$echarts.init(document.getElementById("......
  • React+echarts (echarts-for-react) 画中国地图及省份切换
    有足够的地图数据,可以点击到街道,示例我只出到市级以umi为框架,版本是:"react":"^18.2.0","umi":"^4.0.29","echarts":"^5.4.0","echarts-for-rea......
  • ECharts基础概念
    简要介绍下ECharts中的基础概念:1、echarts实例:一个网页中可以创建多个echarts实例。每个echarts实例中可以创建多个图表和坐标系等。dom节点作为echarts的渲染容器,......
  • Python量化中用pyecharts画K线示例
    首先需要安装Python软件,以及pyecharts库相关教程链接:龙哥量化:文档目录(股票,期货,通达信、同花顺、文华等软件使用,Python量化交易,策略编写,学习文档,策略案例等等) 1"""......
  • 在 iOS 16 中用 SwiftUI Charts 创建一个折线图
    前言苹果在WWDC2022上推出了SwiftUI图表,这使得在SwiftUI视图中创建图表变得异常简单。图表是以丰富的格式呈现可视化数据的一种很好的方式,而且易于理解。本文展示了......
  • 字符串charAt,indexOf,startsWith,endsWith,matches,StringBuffer的reverse().toString(),C
    一、字符串字符串charAt,indexOf,startsWith,endsWith,matches,splitString[]arr=str.split(",");二、数组Integer[]arr={1,3,5,2,4,6};//默认升序Arrays.sort(arr)......
  • 24. echarts 可以画哪些图表
    1.折线图2.柱状图3.饼图 4.地图5.雷达图 延申问题:画折线图和柱状图哪些配置可以改变样式 1.  color 设置每个数据的颜色2. grid网格设......
  • 在线echarts编辑器实现
    一、简介本文主要介绍如何开发一个同echarts官网里面在线echarts编辑工具,通过页面中的代码编辑器修改echarts的option属性来实时渲染echarts的展示效果。其中主要使用到了......
  • vue项目echarts图表自适应
     1、首先新建一个js文件,用来自定义一个全局指令:  2、然后在main.js中引入:  3、然后在自己使用的echarts上加入此指令! ......
  • Echarts Y轴网格线宽度调整
    yAxis:{show:false,type:"value",axisTick:{show:false,},show:true,axisLabel:{show:true,......