正则表达式的学习

最近写了一个匹配以什么什么开头,以什么什么结尾的,且字符串长度不超过多少的正则

pattern = re.compile(r’肌酐[\w|:|/|↑|.| |(|)|:|\u4e00-\u9fa5]{,20}L’) #/&;/g [\u4e00-\u9fa5]

(此处为以肌酐开头,以L结尾的匹配)

p.append(pattern)

在学习时,注意到了/g这个用法,能让match函数返回多个值,然后是\.来匹配点

还有没有非某个范围的说法,比如企图用/|\u4e00-\u9fa5]来匹配不是中文的一切东西是不行的

然后是group的用法,这就是个分组

如果正则里面有小括号部分,括起来的就是分组,第一个是分组1,第二个是分组2

例子

import re
pattern = re.compile(‘(\d+).(\d)?’)
s=’肌酐(Cr): 456,187.0μmol/L546.555′
searchObj = re.search(pattern, s, flags=0)
print(searchObj.group(1))

只能匹配某个范围,没有非

了解到 ?* 和 {,20} 从某种程度来说,很像,?*只是一个没有确定值的范围,尽可能少

了解到断言?:

首先,正则表达式的”非”,代表不想匹配某个字符。

比如字符串 helloword123,/[^0-9]+/g 可以匹配非数字,即匹配结果为 helloword;

同样的,/[^he]+/g 可以匹配非h非e的字符,匹配结果为lloword123;

那么 /[^hello]/g 呢?乍一看可能会以为能匹配word123,其实不然,[^] 内的多个字符是”或”的关系存在的,即它们并不是一个整体,/[^hello]/g 表示 非h非e非l非o,并不能理解为 非(hello),所以匹配结果是 w 和 rd123。

道理我们都懂,可我们就是想匹配非某个字符串呢?比如某一字符串若是含有hello则无匹配,若是不含hello则匹配,写成[^hello]是显然不行的,[^(hello)] 呢?其实不起作用。

这时我们需要用到正则表达式的断言——(?!pattern) 零宽负向先行断言 或者 (?<!pattern) 零宽负向后行断言 均可。

这里只介绍一种写法,大家可以都去尝试一下。

/^((?!hello).)+$/

由于断言 (?!hello)是不占位的,后跟的 . 在原位置匹配任意字符,再用括号将其括起来,用+重复一次或多次,前后加上^和$,若是字符串中存在hello,则匹配到h字符之前的时候,断言(?!hello)匹配失败,正则匹配结果为false, 若是字符串中不存在hello,则匹配结果是整个字符串。

用法实战

  1. 匹配&和;之间不含有test的字符

str = “hello&nbsp; &test1;test&qout;”;

正则表达式:/&((?!test).)+;/g

匹配结果:&nbsp;和 &qout;

2.匹配不含有标签的标签

str = “<div id=’1′><img class=’xx’></div><div id=’1′><input type=”text”></div>“;

正则表达式: /<div[^>]*>((?!<img[^>]*>).)+</div>/g

匹配结果:<div id=’1′><input type=”text”></div>

享受学习

坚持做某一件事,热爱是一个不可缺少的原因。这是真正能提供你源源不断的动力的根本所在。做任何事情也是如此,不是为了争名逐利,只是单纯的享受过程,喜欢某件事情本身,这样即便会带来挫败,也不会让你望而却步或者干脆放弃。

HBTCM寒假第一次积分赛

A – HangOver

题目大意就是求1/2+1/3+…+1/n+1的值大于给的数时,n为多少

代码:

#include<iostream>
#include<cstdlib>
using namespace std;

int main(){
    double n,sum;
    int t;
    while(cin>>n){
        if(n==0) break;
        sum=0;
        for(int i=1;i>=-1;i++){
            if(sum>=n) {cout<<t<<" card(s)"<<endl;break;}
            t=i;
           // cout<<1<<"/"<<t+1<<endl;
            sum+=1.0/(t+1)*1.0;
           // cout<<sum<<endl;
        }
    }
    return 0;
}

B – 回文数

HRBUST – 1280 

题目吐槽:此题不需要文件读入读出…..然后是有一个函数itoa可以方便进制转换,可以自己手写,也可以调用,只是不知道为什么老师只给了g++的编译器,而g++编译器恰好只支持atoi不支持itoa,只好手动copy一份百度itoa代码,原itoa在c++中应存在并且头文件为
<stdlib.h>(C++版本:<cstdlib>)

题目理解:进行进制转换

#include<iostream>
#include <string>
#include <string.h>
#include <cstring>
#include <cstdlib>
using namespace std;


bool huiwen(char *s){
    int len=strlen(s);
    for(int i=0;i<len/2;i++){
        if(s[i]==s[len-i-1]) continue;
        return false;
    }
    return true;
}
bool hanshu(int S){
    int i,coun=0;
    char s[10000];
    for(i=2;i<=10;i++){
        itoa(S,s,i);
        if(huiwen(s)) coun++;
        if(coun==2) return true;
    }
    return false;
}

int main(){
    int N,S,coun=0,t;
    while(cin>>N>>S){
        S++;
        cout<<"Case "<<++coun<<":"<<endl;
        for(int i=0;i<N;i++){
            if(!hanshu(S))
                i--;
            else cout<<S<<endl;
            S++;
        }
    }
    return 0;
}

C – 字数统计

HDU – 1735 

#include<iostream>
#include <string>
#include <string.h>
#include <cstring>
#include <iomanip>
#include <algorithm>
using namespace std;
int s[10000+5][100+5];
int main(){
    int N,L,M,i,j,counM,counD,counO,z,coun;
    int d[10000+5];
    while(cin>>N>>L>>M){
        memset(d,0,sizeof(d));
        counM=counD=counO=0;
        for(i=0;i<N;i++){
            for(j=0;j<L;j++){
                cin>>s[i][j];
                if(s[i][j]==0) counO++;
                if(j==1) {
                    if(s[i][0]==0&&s[i][1]==0) {
                        counM++;
                        if(i!=0){
                            z=L-1;
                            while(s[i-1][z]==0){
                                d[i-1]++;
                                z--;
                            }
                        }
                    }

                }
            }
        }
        z=L-1;
        while(s[i-1][z]==0){
            counO--;
            z--;
        }
        //cout<<counO<<" "<<counM<<endl;
        sort(d,d+N);
        coun=M-1;
        for(i=N-1;i>=N-counM-1;i--){
            if(coun--==0) break;
         //   cout<<d[i];
          //  cout<<d[i]<<endl;
            counO-=d[i];
        }
        cout<<counO-2*M<<endl;
    }



    return 0;
}

D – 最小周长

51Nod – 1283 

#include<iostream>
#include <string>
#include <string.h>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cmath>
using namespace std;
int main(){
    int S;
    cin>>S;
    for(int i=(int)sqrt(S);i>=1;i--){
        if(S%i==0) {
           cout<<2*(i+S/i)<<endl;
           break;
        }
    }
    return 0;
}

E – 迷宫城堡

HDU – 1269 

#include<iostream>
#include <string>
#include <string.h>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
const int MAXN=100000;
int vis[MAXN];
int dfn[MAXN];
int low[MAXN];
int c_time;
int flag;
vector<int> mp[MAXN];
void tarjan(int u)//tarjan算法
{
    vis[u]=1;
    low[u]=dfn[u]=c_time++;
    for(int i=0; i<mp[u].size(); i++)
    {
        int v= mp [u][i];
        if(vis[v]==0) tarjan(v);    //如何没访问过
        if(vis[v]==1) low[u]=min(low[u],low[v]);    //如果访问过
    }
    if(dfn[u]==low[u])
        flag++;
}
int main(){
    int n,m,x,y;
    while(cin>>n>>m){
        if(n==0&&m==0) break;
        memset(low,0,sizeof(low));  //初始化
        memset(vis,0,sizeof(vis));
        memset(dfn,0,sizeof(dfn));
        for(int i=1; i<=n; i++) mp[i].clear();
        for(int i=0; i<m; i++)
        {
            cin>>x>>y;
            mp[x].push_back(y);
        }
        c_time=1;
        flag=0;
        for(int i=1; i<=n ; i++)
        {
            if(vis[i] == 0)
            {
                tarjan(i);
            }
        }
        if(flag==1)
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    }
    return 0;
}

在补了在补了(

moc3型live2D如何在网页上使用

前言 之前搞网页 Live2d 模型的时候在网上找了很多文章,但大部分都只支持moc格式的模型,不支持moc3格式的模型。 最近在Github上看到这个项目AzurLaneL2DViewer, 使用前请查看live2dcubismcore的许可协议 HCLonely Live2dV3 021efa , up-to-date HCLonely Live2dV3 021efa , up-to-date 使用方法 在标签内添加如下内容:

<div class="Canvas" style="position:fixed;right:250px; bottom: -100px;z-index: 99999999" id="L2dCanvas"></div>
<!------ 依赖 JS ------>
<!---- 可选 ---->
<!-- 兼容低版本浏览器 -->
<script src="http://www.xiaocongyu.com/live2d/js/polyfill.min.js"> </script>
<!-- 音频播放兼容 -->
<script src="http://www.xiaocongyu.com/live2d/js/howler.min.js"></script>
<!---- 必需 ---->
<script src="http://www.xiaocongyu.com/live2d/js/live2dcubismcore.min.js"></script>
<script src="http://www.xiaocongyu.com/live2d/js/pixi.min.js"></script>
<!-- live2dv3.js -->
<script src="http://www.xiaocongyu.com/live2d/yu3/live2dva.min.js"></script>
<!------ 加载Live2d模型 ------>
<script>
window.onload = () => {
    new l2dViewer({
        el: document.getElementById('L2dCanvas'), // 要添加Live2d的元素, 支持dom选择器和jq选择器
			//basePath: 'https://cdn.jsdelivr.net/npm/live2dv3@latest/assets',
        //modelName: 'biaoqiang_3',
        basePath: 'http://www.xiaocongyu.com/live2d', // 模型根目录
        modelName: 't4', // 模型名称
			width: 200,
			height: 600,
			mobileLimit: false,
        sounds: [ // 触摸播放声音
            'http://www.xiaocongyu.com/live2d/sounds/buhaixiuma.mp3' ,// 也可以是网址
				 'http://www.xiaocongyu.com/live2d/sounds/haixiu.mp3'
        ]
		
    })
}
</script>

HTML 复制 参数 参数 类型 描述 默认 el [必需] DOM 对象或 jQuery 对象 要挂载 Live2d 模型的元素, 支持 DOM 选择器和 jQuery 选择器,例:document.getElementById(‘L2dCanvas’)或document.querySelector(‘#L2dCanvas’)或$(‘#L2dCanvas’) null basePath [必需] String 模型根目录 null modelName [必需] String 模型目录 null width [可选] Number Canvas 宽度,单位:px 500 height [可选] Number Canvas 高度,单位:px 300 sizeLimit [可选] Boolean 当窗口大小小于设置的宽或高时不加载模型 false mobileLimit [可选] Boolean 移动端不加载模型 false sounds [可选] Array 触摸播放声音, 留空则不播放 null 方法 loadModel(modelName?) 重新加载/更换模型

特征选择和降维

1、相同点和不同点

  特征选择和降维有着些许的相似点,这两者达到的效果是一样的,就是试图去减少特征数据集中的属性(或者称为特征)的数目;但是两者所采用的方式方法却不同:降维的方法主要是通过属性间的关系,如组合不同的属性得新的属性,这样就改变了原来的特征空间;而特征选择的方法是从原始特征数据集中选择出子集,是一种包含的关系,没有更改原始的特征空间。

2、降维的主要方法

特征选择的目标

  引用自吴军《数学之美》上的一句话:一个正确的数学模型应当在形式上是简单的。构造机器学习的模型的目的是希望能够从原始的特征数据集中学习出问题的结构与问题的本质,当然此时的挑选出的特征就应该能够对问题有更好的解释,所以特征选择的目标大致如下:

  • 提高预测的准确性
  • 构造更快,消耗更低的预测模型
  • 能够对模型有更好的理解和解释

特征选择的方法

  主要有三种方法:

1、Filter方法

  其主要思想是:对每一维的特征“打分”,即给每一维的特征赋予权重,这样的权重就代表着该维特征的重要性,然后依据权重排序。

  主要的方法有:

2、Wrapper方法

  其主要思想是:将子集的选择看作是一个搜索寻优问题,生成不同的组合,对组合进行评价,再与其他的组合进行比较。这样就将子集的选择看作是一个是一个优化问题,这里有很多的优化算法可以解决,尤其是一些启发式的优化算法,如GA,PSO,DE,ABC等,详见“优化算法——人工蜂群算法(ABC)”,“优化算法——粒子群算法(PSO)”。

  主要方法有:recursive feature elimination algorithm(递归特征消除算法)

3、Embedded方法

  其主要思想是:在模型既定的情况下学习出对提高模型准确性最好的属性。这句话并不是很好理解,其实是讲在确定模型的过程中,挑选出那些对模型的训练有重要意义的属性。

  主要方法:正则化,可以见“简单易学的机器学习算法——岭回归(RidgeRegression)”,岭回归就是在基本线性回归的过程中加入了正则项。

总结以及注意点

  这篇文章中最后提到了一点就是用特征选择的一点Trap。个人的理解是这样的,特征选择不同于特征提取,特征和模型是分不开,选择不同的特征训练出的模型是不同的。在机器学习=模型+策略+算法的框架下,特征选择就是模型选择的一部分,是分不开的。这样文章最后提到的特征选择和交叉验证就好理解了,是先进行分组还是先进行特征选择。

  答案是当然是先进行分组,因为交叉验证的目的是做模型选择,既然特征选择是模型选择的一部分,那么理所应当是先进行分组。如果先进行特征选择,即在整个数据集中挑选择机,这样挑选的子集就具有随机性。

  我们可以拿正则化来举例,正则化是对权重约束,这样的约束参数是在模型训练的过程中确定的,而不是事先定好然后再进行交叉验证的。

  以上是我学习的一点感悟,希望有更多的人一起参加讨论,如有哪里写的不对或者有其他任何问题,也希望能够留言。

参考文献:

An Introduction to Feature Selection 地址:http://machinelearningmastery.com/an-introduction-to-feature-selection

Java中Map根据键值(key)或者值(value)进行排序实现

我们都知道,java中的Map结构是key->value键值对存储的,而且根据Map的特性,同一个Map中 不存在两个Key相同的元素,而value不存在这个限制。换句话说,在同一个Map中Key是唯一的,而value不唯一。Map是一个接口,我们不能 直接声明一个Map类型的对象,在实际开发中,比较常用的Map性数据结构是HashMap和TreeMap,它们都是Map的直接子类。如果考虑到存取 效率的话,建议使用HashMap数据结构,而如果需要考虑到Key的顺序,建议使用TreeMap,但是TreeMap在删除、添加过程中需要排序,性能比较差。

1 、 以Key进行排序
我们可以声明一个TreeMap对象

Map<Integer, Person> map = new TreeMap<Integer, Person>();

然后往map中添加元素,可以通过输出结果,可以发现map里面的元素都是排好序的

//遍历集合for (Iterator<Integer> it = map.keySet().iterator(); it.hasNext();) {Person person = map.get(it.next());System.out.println(person.getId_card() + " " + person.getName());}

我们也可以声明一个HashMap对象,然后把HashMap对象赋值给TreeMap,如下:

Map<Integer, Person> map = new HashMap<Integer, Person>();TreeMap treemap = new TreeMap(map);

2、以Value进行排序
先声明一个HashMap对象:

Map<String, Integer> map = new HashMap<String, Integer>();

然后我们可以将Map集合转换成List集合中,而List使用ArrayList来实现如下:

List<Entry<String,Integer>> list =new ArrayList<Entry<String,Integer>>(map.entrySet());

最后通过Collections.sort(List l, Comparator c)方法来进行排序,代码如下:

Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {public int compare(Map.Entry<String, Integer> o1,Map.Entry<String, Integer> o2) {return (o2.getValue() - o1.getValue());}});

上述代码是讲map中的value按照逆序排序,如果需要按照升序进行排序的话,只需要修改o2.getValue() – o1.getValue()为o1.getValue() – o2.getValue()即可

关于欧拉函数的一些理解与拓展

很早之前就只知道一点欧拉函数的使用,现在来总结一下,有哪些我没懂的和我懂了的

欧拉定理

欧拉定理,也称费马-欧拉定理,若n,a为正整数,且n,a互质,即gcd(a,n) = 1,则a^φ(n) ≡ 1 (mod n)

欧拉函数

欧拉函数是求小于等于n的数中与n互质的数的数目  

如果n是质数那么1到n-1所有数都是与n互质的,所以φ(n) = n-1如果n是合数。。。自己算吧例如φ(8)=4,因为1,3,5,7均和8互质

请思考以下问题:

任意给定正整数n,请问在小于等于n的正整数之中,有多少个与n构成互质关系?(比如,在1到8之中,有多少个数与8构成互质关系?)

计算这个值的方法就叫做欧拉函数,以φ(n)表示。在1到8之中,与8形成互质关系的是1、3、5、7,所以 φ(n) = 4。

φ(n) 的计算方法并不复杂,但是为了得到最后那个公式,需要一步步讨论。

第一种情况

如果n=1,则 φ(1) = 1 。因为1与任何数(包括自身)都构成互质关系。

第二种情况

如果n是质数,则 φ(n)=n-1 。因为质数与小于它的每一个数,都构成互质关系。比如5与1、2、3、4都构成互质关系。

第三种情况

如果n是质数的某一个次方,即 n = p^k (p为质数,k为大于等于1的整数),则

2015-08-04/55c0573f4a25a

比如 φ(8) = φ(2^3) =2^3 – 2^2 = 8 -4 = 4。

这是因为只有当一个数不包含质数p,才可能与n互质。而包含质数p的数一共有p^(k-1)个,即1×p、2×p、3×p、…、p^(k-1)×p,把它们去除,剩下的就是与n互质的数。

上面的式子还可以写成下面的形式:

2015-08-04/55c0578076585

可以看出,上面的第二种情况是 k=1 时的特例。

第四种情况

如果n可以分解成两个互质的整数之积,

n = p1 × p2

φ(n) = φ(p1p2) = φ(p1)φ(p2)

即积的欧拉函数等于各个因子的欧拉函数之积。比如,φ(56)=φ(8×7)=φ(8)×φ(7)=4×6=24。

这一条的证明要用到“中国剩余定理”,这里就不展开了,只简单说一下思路:如果a与p1互质(a<p1),b与p2互质(b<p2),c与p1p2互质(c<p1p2),则c与数对 (a,b) 是一一对应关系。由于a的值有φ(p1)种可能,b的值有φ(p2)种可能,则数对 (a,b) 有φ(p1)φ(p2)种可能,而c的值有φ(p1p2)种可能,所以φ(p1p2)就等于φ(p1)φ(p2)。

第五种情况

2015-08-04/55c057f99f735

因为任意一个大于1的正整数,都可以写成一系列质数的积。

2015-08-04/55c05835ca6e2

根据第4条的结论,得到

再根据第3条的结论,得到

2015-08-04/55c05871f2594

也就等于

2015-08-04/55c058b16129e

这就是欧拉函数的通用计算公式。比如,1323的欧拉函数,计算过程如下:

2015-08-04/55c059446c936

欧拉公式

还有一个欧拉公式eix = cosx + isinx

把x代入公式就是, eiπ + 1 = 0

引用一个名人的话(我忘了是谁( ̄▽ ̄lll)):”它把自然对数e,虚数i,无理数π,自然界中的有和无(1和0)巧妙的结合了起来,上帝如果不存在,怎么会有这么优美的公式。如何见到它第一眼的人没有看到它的魅力,那它一定成不了数学家”

费马小定理

由欧拉函数的特例,如果n是质数,则可得欧拉定理 a^(n-1)≡ 1 (mod n)