Quantcast
Channel: CSDN博客推荐文章
Viewing all 35570 articles
Browse latest View live

从零开始前端学习[55]:类型转换和Math方法

$
0
0

类型转换和Math方法

  1. 类型转换(显示类型转换,隐式类型转换)
  2. Math方法

提示:
博主:章飞_906285288
博客地址:http://blog.csdn.net/qq_29924041


类型转换(显示类型转换,隐式类型转换)

我们知道在js中的检测类型方式:typeof 要转换的变量或者数据类型,返回一个类型名称的字符串
而其中显式类型转换,其实就是通过js中的一些方法(函数)转换,如parseInt,parseFloat等

显示转换

显示转换有时候常用的一些转换函数:parseInt,parseFloat,toString等类型。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <meta charset="UTF-8"><!--申明当前网页的编码集UTF-8-->
  <meta name="Generator" content="EditPlus®">   <!--编辑器的名称-->
  <meta name="Author" content="作者是谁">       
  <meta name="Keywords" content="关键词">
  <meta name="Description" content="描述和简介">
  <style type="text/css">                                        
        body,dl,dd,dt,p,h1,h2,h3,h4,h5,h6{ margin: 0;}
        ul,ol{margin: 0; list-style: none; padding: 0;}
        a{ text-decoration: none; }
        *{ margin: 0; padding: 0; }
  </style>
</head>
<body>
<script>
  var demo_int = 10;   //定义一个整形数据
  console.log("demo_int:"+ demo_int);
  console.log("demo_int type:"+ typeof demo_int);

  var demo_string_width = "110.05px"
  console.log("demo_string_width:"+demo_string_width);
  console.log("demo_string_width type:"+typeof demo_string_width);
  console.log("parseInt demo_string_width:"+ parseInt(demo_string_width));  //从字符串类型中过滤出整形
  console.log("parseInt demo_string_width _2:"+ parseInt(demo_string_width,2)); //以二进制形式读取
  console.log("parseInt demo_string_width _16:"+ parseInt(demo_string_width,16));//以16进制形式输出
  console.log("parseInt demo_string_width:"+ parseFloat(demo_string_width)); //从字符串类型中过滤出实形
  var demo_string = "aaasd110.05px"
  console.log("parseInt demo_string:"+ parseInt(demo_string));  //从字符串类型中过滤出整形
  console.log("parseInt demo_string:"+ parseFloat(demo_string));  //从字符串类型中过滤出整形

  var demo_Int2 = 100;
  console.log(typeof  demo_Int2.toString());  //将整型数据转换为字符串型
  console.log(demo_Int2.toString()+"1234");  //将整型数据转为字符串型后,在与数据相加得到一个字符串
</script>
</body>
</html>

上述实测试代码:测试parseInt,parseFloat以及toString类型的使用

这里写图片描述

隐式转换

隐式类型转换,就是在没有任何显示转换的基础上,通过运算符等操作,由浏览器自动为我们进行这样的一种类型转换的过程,其实这种转换自古其实就有,不管在java或者c/C++中都是有的,比如一个整型与实型的相加,乘除等等。这个时候都是会由系统自动去进行一系列的类型转换过程。

1:+ 全为数字类型则为运算,有字符串则为拼接 从左到右计算
2:- ,* , / ,% 只要有一边是数字就将结果直接转换为数字类型
3:对于boolean类型的加减都是按照数字类型来进行的

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <meta charset="UTF-8"><!--申明当前网页的编码集UTF-8-->
  <meta name="Generator" content="EditPlus®">   <!--编辑器的名称-->
  <meta name="Author" content="作者是谁">       
  <meta name="Keywords" content="关键词">
  <meta name="Description" content="描述和简介">
  <style type="text/css">                                        
        body,dl,dd,dt,p,h1,h2,h3,h4,h5,h6{ margin: 0;}
        ul,ol{margin: 0; list-style: none; padding: 0;}
        a{ text-decoration: none; }
        *{ margin: 0; padding: 0; }
  </style>
</head>
<body>
<script>
  //如果加号左右全是数字,就是按照正常数字的形式进行加减
  var allNumberSum = 1 + 2;
  console.log(allNumberSum);
  console.log(typeof allNumberSum);

  //如果其中都是数字类型字符串,如果从左到右数字的话,会先加,遇到字符串就直接拼接成字符串
  var sideofString = 1 + 2 +"3"+"5";
  console.log(sideofString);
  console.log(typeof sideofString);

  //如果其中有数字类型字符串,如果先是字符串,后面是数字的话,会直接转换成字符串
  var sideofString2 ="bbb" + 1 + 3 + "3"+"aaaa";
  console.log(sideofString2);
  console.log(typeof sideofString2);

//  boolean值会被强制转换为数字,true被转为1,false转为0
  var booleanResult = true + false;
  console.log(booleanResult);

//  不是数字类型的字符串 或者   其他类型的运算,结果是NaN(除开加法运算,因为是拼接)不是数字类型的字符串
  var str2 = "str2";
  var sum7 = str2 - 1;
  var str3 = undefined;
  console.log(sum7); //NaN
  console.log(str3 - str2);
</script>
</body>
</html>

注意:隐式类型转换的注意事项主要写在了上述的备注上面
这里写图片描述


Math方法

在任何一门已知的语言中,数学函数Math库的调用都是及其重要的,在js里面当然也是一样的。其调用的形式跟java里面也类似,静态方法的一种调用方法。
相关函数如下所示:

函数 函数意义
Math.ceil() 向上取整
Math.floor() 向下取整
Math.round() 四舍五入
Math.abs() 取绝对值
Math.random() 默认是取从[0,1)之间的随机数
Math.max(a,b) 取最大值 里面个数不限 非数字字符串识别不了
Math.min(a,b) 取最大值 里面个数不限 非数字字符串识别不了
Math.sqrt(x) x的平方根
Math.pow(x,y) x的y次幂

基本上常规用的也就上面这些了,调用都很简单。

作者:qq_29924041 发表于2017/11/26 19:38:17 原文链接
阅读:58 评论:0 查看评论

数据库新动向 Oracle 与微软割据局面产生

$
0
0

转自:http://tech.it168.com/a2017/1120/3180/000003180443.shtml

【IT168 评论】数据库是一个历久弥新的领域,每年有很多新的黑马产生,但是整体局面却又看不出大的变化。究其原因可能是老牌厂商占据了主要市场,新伙伴的加入只能稍改部分局面,却无法撼动大的格局。

  今年,DB-Engines指数和数据库领域都有了一些新的变化,既有新的组合产生,也有高歌猛进的黑马选手,同时也有不进则退的老牌选手。虽然,黑马选手无法撼动大局面,但是新鲜组合的诞生是否会创造出新局面呢?

  Oracle与MySQL的局面或颠覆

  在DB-Engines榜单上,Oracle占据第一位,MySQL千年老二的局面从2013年开始就几乎没有改变过。但是2016年却是一个分水岭,虽然二者的地位没有出现变化,但是从这一年开始,MySQL开始了雄心勃勃的逼宫之旅,而Oracle却从这时开始走上了下滑之路。

数据库领域开始松动,新的局面会诞生吗?

  2016年5月,MySQL与Oracle之间的差距不断缩小,并在2017年6月达到历史最接近点,Oracle综合得分为1351.762,而MySQL综合得分为1345.307,双方相差仅有短短的6.5分。MariaDB是MySQL的一个分支,如果MariaDB+MySQL组合起来对抗Oracle,其实Oracle的霸主地位早已不保。2016年11月, MySQL得分为1373,MariaDB得分为42,双方分数相加已超过Oracle 1413的得分。

  双巨头对垒,新的阵营产生

  上文我们说到,MariaDB是MySQL的一个分支,如果两方联手目前已经撼动了Oracle的霸主地位。但事实却并非如此, MariaDB作为MySQL的创始人Michael Widenius的另一个作品,显然作者并不想走MySQL的老路。所以为了确保MariaDB项目由用户驱动,从一开始,MariaDB就建立了基金会。

  今年11月份,MariaDB找到了大金主微软。据悉,微软作为白金会员加入MariaDB基金会,将为MariaDB的研发提供更强大的物质保障,同时也会提升MariaDB在支持Windows方面功能的水平,并在不久的未来会有一个MariaDB的Azure数据库预览版诞生,这将是一个完全托管的MariaDB的云托管版本。

数据库领域开始松动,新的局面会诞生吗?

  众所周知,Oracle和MySQL现在同属于Oracle公司。而SQL Server作为微软方数据库近几年来表现上佳,但始终没有突破Oracle和MySQL,微软此番加入MariaDB基金会,是否会形成Oracle+MySQL VS SQL Server+MariaDB的新割据呢?巨头对垒,是否会有新的火花产生呢?

  掉入第二梯队的DB2恐难翻身

数据库领域开始松动,新的局面会诞生吗?

  DB2作为数据库佼佼者,曾经也是风光无限,但是最近几年表现平平,已经沦为第二梯队了。近几年来,几乎很少能够听到DB2的声音,反倒是随着"去IOE"运动轰轰烈烈的进行,听到了很多替换DB2的声音。

  如今,DB2的大部分份额都集中在金融系统中。金融业务由于对业务可持续性要求很高,而且对于数据安全性的要求更高,各种风险控制力度也更大,所以DB2不会轻易被替换。但是我们最近走访了一些金融企业,发现很多企业已经在着手替换DB2,而有些企业虽然没有替换DB2的想法,但是主要目的却是为了制衡Oracle,防止一家独大。

  新数据库来势汹汹

数据库领域开始松动,新的局面会诞生吗?

  MongoDB和PostgreSQL作为新数据库的代表近几年的发展可谓是突飞猛进,从上图中我们可以看到,他们两已经远远的将DB2甩在了身后。2017年,关于MongoDB和PostgreSQL的声音也是不少,如MongoDB IPO,中国开源软件推进联盟PostgreSQL分会成立等等。

  在应用方面,二者也是颇受开发者和企业关注。国外知名 IT 技术媒体 Jaxenter 对2017年数据库趋势做了调查,其中63%的调查者表示对PostgreSQL很感兴趣,而49.8%的调查者表示对MongoDB很感兴趣。根据我们对于金融行业数据库选型的调研,MongoDB和PostgreSQL目前在金融行业均有应用。


作者:yanzongshuai 发表于2017/11/26 19:39:26 原文链接
阅读:59 评论:0 查看评论

linux vim编辑器之常用指令

$
0
0

- 移动光标

1.h,j,k,l分别对应←,↓,↑,→。所以向下移动30行可以使用30j或者302.PageUp,PageDown对应向上,向下移动一页

3.n+空格键 表示光标向后移动n个字符距离

4.0或者home表示移动这一行最前面字符处,$或者end表示移动到这一行最后面字符处

5.H,M,L分别对应光标移动到这个屏幕的最上方,中央,最下方那一行的第一个字符处

6.G移动到这个文件的最后一行

7.nG,光标移动到这个文件的第n行

8.gg,光标移动到这个文件的第一行,相当于1G

9.n加enter键,光标向下移动n行

- 查找替换

1./word,?Word,分别对应向下,向上寻找一个名称为word的字符串

2.n,N 分别对应重复前一个查找操作和反向查找。比如使用/lala,表示向下
查找lala这个字符串,按n则表示重复向下查找,而按N则表示向上查找。

3.:n1,n2s/word1/word2/g   n1,n2为数字,表示在n1行和n2行之间查找
word1这个字符串,并将word1替换成word2这个字符串

4.:1,$s/word1/word2/g   从第一行到最后一行之间查找word1这个字符,并
将word1字符替换成word2这个字符

5.:n1,n2ss/word1/word2/gc   从第n1行到n2行之间查找word1这个字符,并
将word1字符替换成word2这个字符,且在替换之前显示提示字符给用户确认
(confirm)是否需要替换

- 删除复制粘贴

1.x,X  在一行字当中,x为向后删除一行(相当于delete键),X为向前删除一
个字符(相当于backspace键),nx 连续向后删除n个字符,nX连续向前删除n个
字符

2.dd 删除光标所在的那一整行,并将该行复制下来,通常会结合p一起使用,使
用ddp可以将一整行移动到其它的位置。ndd删除光标所在向下n行,并将该n行复
制下来,也可以结合p将该n行粘贴在其它位置

3.d1G,dG,d$,d0  分别对应删除光标所在到第一行的所有数据,删除光标所
在到最后一行的所有数据(dG可以结合p来将该文件全部数据复制下来,不过这种
全部复制会删除该文件所有的数据,可以使用u将该文件恢复到原来的样子,再用p
将数据粘贴到其它文件中,后面会写一篇多窗口,多文本编辑的文章,和这些指令
结合起来使用相当的方便),删除从光标所在处到该行最后一个位置,删除从光标
所在处到该行最前面的一个字符

4.yy,nyy,y1G,yG,y0,y$  分别对应复制光标所在那一行,复制光标向下n
行,复制光标所在行到第一行的所有数据,复制光标所在行到最后一行的所有数
据,复制光标所在处到改行行首的所有数据,复制光标所在处到改行行尾的所有数
据

5.p,P  字母p为粘贴操作,小写的p将复制的数据从光标所在行下一行开始粘
贴,大写的P将复制的数据从光标所在行上一行开始粘贴。p或者P经常会结合dd,
yy等操作一起使用

6.J 将光标所在行与下一行的数据结合成一行

7.u 复原到前一个状态

8.Ctrl加r 复原到后一个状态,Ctrl+r指令可以说和u是反着来的。举个例子:
现在有一个文件里面的内容是四行字符串如下
One
Two
Three
Four
我现在使用dd指令分别按顺序删除OneTwoThree三行。假设删除One时文件状
态为1,删除Two时文件状态是2,删除Three时文件状态是3。现在文件是状态3,
这个文本只剩下Four这个字符串了,此时我连续按下两次u,则会按顺序先恢复到
状态2,在恢复到状态1。现在文件是状态1有三行内容TwoThreeFour。此时
我再按下Ctrl+r组合键,文件会恢复到后一个状态也就是状态2,文件内容
是ThreeFour这两行字符串。若又按下u文件又恢复到了状态1了。可以看出
来Ctrl+r和u这两个指令就是互为反操作

9.. 这是一个小数点,这个指令是重复前一个操作的意思,其实重复操作一个指
令就可以了,没必要记住这个指令。

- 一般模式切换到编辑模式

1.i,I 进入到插入模式,i为从目前光标处插入,I为目前所在行第一个非空格字
符处开始插入

2.a,A 进入到插入模式,a为从目前光标所在的下一个字符处开始插入,A为光标
所在行最后一个字符处开始插入

3.o,O 进入到插入模式,o光标目前所在行下一行开辟新的一行开始插入,O光标
目前所在行上一行开辟新的一行开始插入

r,R  进入替换模式,r只会替换光标所在的那个字符一次。R会一直替换光标所
在的字符,直到按下esc为止

- 一般模式切换到命令行模式

1.:w:w!,:q:q! 分别对应数据写入硬盘(就是保存,不过这种保存因为没
有退出,还是可以使用u来恢复),数据强制写入(能不能强制跟文件权限有
关),退出vim,强制退出(文件有修改,退出时会要求是否保存,使用q!可以强
制不保存退出)

2.:wq  保存退出文件

3.:w[filename] 将编辑的数据保存为另一个文件(另存为)

4.:r[filename] 在编辑数据时,读入另一个文件的数据,即将”filename”这
个文件内容加到光标所在行后面

5.n1,n2 w [filename]n1n2之间的内容保存在”filename”这个文件中

6.:! command 暂时离开vim到命令行模式下执行其它的指令。比如我在编辑文件
的时候想要显示当前目录下的文件有哪些,可以执行”:! ll .”  即可以暂时离
开vim模式查看该文件所在目录目前有哪些文件,再随便按任意键即可以回到vim
模式

7.:set nu   :set nonu  分别表示显示行号和不显示行号

以上这些是vim的一些常用指令,会了这些指令你会发现vim非常好使,这些指令还是有些规律的,复制yy,粘贴p,替换r,删除dd,再和数字相结合就会出现多行操作的效果,还有一些大小写不同就会出现在不同位置操作的效果,多使用几次就记下来了。

作者:u012062455 发表于2017/11/26 19:40:25 原文链接
阅读:47 评论:0 查看评论

UVa12096集合栈计算机(集合操作)

$
0
0

刘汝佳紫书例题5-5  P115

Background from Wikipedia: “Set theory is a
branch of mathematics created principally by the
German mathematician Georg Cantor at the end of
the 19th century. Initially controversial, set theory
has come to play the role of a foundational theory
in modern mathematics, in the sense of a theory
invoked to justify assumptions made in mathematics
concerning the existence of mathematical objects
(such as numbers or functions) and their properties.
Formal versions of set theory also have a foundational
role to play as specifying a theoretical ideal
of mathematical rigor in proofs.”
Given this importance of sets, being the basis of mathematics, a set of eccentric theorist set off to
construct a supercomputer operating on sets instead of numbers. The initial SetStack Alpha is under
construction, and they need you to simulate it in order to verify the operation of the prototype.
The computer operates on a single stack of sets, which is initially empty. After each operation, the
cardinality of the topmost set on the stack is output. The cardinality of a set S is denoted |S| and is the
number of elements in S. The instruction set of the SetStack Alpha is PUSH, DUP, UNION, INTERSECT,
and ADD.
• PUSH will push the empty set {} on the stack.
• DUP will duplicate the topmost set (pop the stack, and then push that set on the stack twice).
• UNION will pop the stack twice and then push the union of the two sets on the stack.
• INTERSECT will pop the stack twice and then push the intersection of the two sets on the stack.
• ADD will pop the stack twice, add the first set to the second one, and then push the resulting set
on the stack.
For illustration purposes, assume that the topmost element of the stack is
A = {{}, {{}}}
and that the next one is
B = {{}, {{{}}}}
For these sets, we have |A| = 2 and |B| = 2. Then:
• UNION would result in the set {{}, {{}}, {{{}}}}. The output is 3.
• INTERSECT would result in the set {{}}. The output is 1.
• ADD would result in the set {{}, {{{}}}, {{},{{}}}}. The output is 3.
Input
An integer 0 ≤ T ≤ 5 on the first line gives the cardinality of the set of test cases. The first line of each
test case contains the number of operations 0 ≤ N ≤ 2000. Then follow N lines each containing one of
the five commands. It is guaranteed that the SetStack computer can execute all the commands in the
sequence without ever popping an empty stack.
Output
For each operation specified in the input, there will be one line of output consisting of a single integer.
This integer is the cardinality of the topmost element of the stack after the corresponding command
has executed. After each test case there will be a line with ‘***’ (three asterisks).
Sample Input
2
9
PUSH
DUP
ADD
PUSH
ADD
DUP
ADD
DUP
UNION
5
PUSH
PUSH
ADD
PUSH
INTERSECT
Sample Output
0
0
1
0
1
1
2
2
2
***
0
0
1
0
0
***

【分析】集合栈计算机

把集合映射成数字,集合里套集合,就转变成装数字了

这里需要一个vector保存不同的集合,每个元素是set,下标代表集合的编号。

还需要一个map映射,帮助快速得到集合的编号

另外需要一个stack模拟本题过程。


这里用到了几个比较实用的STL函数:

set_union             求并集
set_intersection   求交集

【代码】:

#include<bits/stdc++.h>
using namespace std;
vector<set<int> >vec;//int编号映射集合
map<set<int>,int>M;
stack<int>sta;
void push(set<int>S)
{
    if(vec.size()==0||vec[M[S]]!=S){
        M[S]=vec.size();
        vec.push_back(S);
    }
    sta.push(M[S]);
}
void uia(int flag)
{
    int u=sta.top();sta.pop();
    int v=sta.top();sta.pop();
    set<int>S1;
    if(flag==0)
        set_union(vec[u].begin(),vec[u].end(),vec[v].begin(),vec[v].end(),inserter(S1,S1.begin()));
    if(flag==1)
        set_intersection(vec[u].begin(),vec[u].end(),vec[v].begin(),vec[v].end(),inserter(S1,S1.begin()));
    if(flag==2)
    {
        S1=vec[v];
        S1.insert(u);
    }
    push(S1);
}
int main()
{
    int T,n;
    string s;
    set<int>S;
    cin>>T;
    while(T--)
    {
        M.clear();
        vec.clear();
        while(!sta.empty())sta.pop();
        cin>>n;
        while(n--)
        {
            cin>>s;
            if(s[0]=='P')
                push(S);
            if(s[0]=='D'&&!sta.empty())
                sta.push(sta.top());
            if(s[0]=='U')uia(0);
            if(s[0]=='I')uia(1);
            if(s[0]=='A')uia(2);
            cout<<vec[sta.top()].size()<<endl;
        }
        cout<<"***"<<endl;
    }
}


作者:winter2121 发表于2017/11/26 20:42:16 原文链接
阅读:43 评论:0 查看评论

Kotlin学习(十八): 委托模式(Delegate)和委托属性(Delegate Properties)

$
0
0

Tooling

委托模式已经被证明是实现继承的一个很好的替代方式,在扩展一个基类并且重写方法时,基类就必须依赖子类的实现,当不断地修改的时候,基类就会失去当初的性质,Kotlin中就将类默认为final,确保不会被修改。

有一种模式是装饰器模式,本质就是创建一个新类,实现与基类一样的接口,并且将类的实现作为一个字段保存,这样就能在基类不被修改就能直接修改基类的实例。但是这样的缺点是会造成很多的样板代码。

class DelegatingCollection<T> : Collection<T> {
    private val innerList = mutableListOf<T>()
    override val size: Int
        get() = innerList.size

    override fun contains(element: T): Boolean = innerList.contains(element)

    override fun containsAll(elements: Collection<T>): Boolean = innerList.addAll(elements)

    override fun isEmpty(): Boolean = innerList.isEmpty()

    override fun iterator(): Iterator<T> = innerList.iterator()

}

当你实现Collection接口的时候,需要重写这几个方法,这里面的代码量是很多的,但是如果用了委托,那么代码就是这样的

class DelegatingCollection2<T>(innerList: Collection<T> = mutableListOf<T>()) : Collection<T> by innerList

这么简单?就能实现那几个方法?我们来看一下生成的代码

是不是省去了很多手写的代码量,下面我们来介绍这种属性。

委托模式(Delegate)

Kotlin支持委托模式,是允许对象组合实现与继承相同的代码复用的,简单来说就是操作的对象不用自己去执行,而是将任务交给另一个对象操作,这样的模式就叫委托模式,被操作的对象叫委托

委托模式是有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。

类委托

同样我们用上面集合的栗子,现在我们已经是委托到一个对象了,如果我们要修改集合里面的方法的时候,可以直接重写,而不用重复的去写新的方法,下面我们来在一个集合里面插入数据,并且获取插入的次数。

下面代码是默认实现MutableCollection接口,获取插入的次数

class DefaultCollection<T> : MutableCollection<T> {
    private val innerList = mutableListOf<T>()
    private var addedSum = 0

    override fun add(element: T): Boolean {
        addedSum++
        return innerList.add(element)
    }

    override fun addAll(elements: Collection<T>): Boolean {
        addedSum += elements.size
        return innerList.addAll(elements)
    }
    override val size: Int
        get() = innerList.size

    override fun contains(element: T): Boolean = innerList.contains(element)

    override fun containsAll(elements: Collection<T>): Boolean = innerList.addAll(elements)

    override fun isEmpty(): Boolean = innerList.isEmpty()

    override fun iterator(): MutableIterator<T> = innerList.iterator()

    override fun clear() = innerList.clear()

    override fun remove(element: T): Boolean = innerList.remove(element)

    override fun removeAll(elements: Collection<T>): Boolean = innerList.removeAll(elements)

    override fun retainAll(elements: Collection<T>): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

}

实现类委托

class DelegatingCollection3<T>(private val innerList: MutableCollection<T> = HashSet<T>()) : MutableCollection<T> by innerList {
    private var addedSum = 0

    override fun add(element: T): Boolean {
        addedSum++
        return innerList.add(element)
    }

    override fun addAll(elements: Collection<T>): Boolean {
        addedSum += elements.size
        return innerList.addAll(elements)
    }
}

是不是省去很多无用的代码,只需要重写我们需要的方法addaddAll,其他没有写出来的方法全部都交给委托来实现。

而且没有对底层集合的实现方法引入任何的依赖,所以对被调用的操作具有完全的控制,如不用担心集合是不是通过循环中调用add来实现addAll

委托属性(Delegate Properties)

有一种属性,在使用的时候每次都要手动实现它,但是可以做到只实现一次,并且放到库中,一直使用,这种属性称为委托属性。
委托属性包括:
- 延迟属性(lazy properties):数据只在第一次被访问的时候计算。
- 可观察属性(observable properties):监听得到属性变化通知。
- Map委托属性(Storing Properties in a Map):将所有属性存在Map中。

class Foo {
    var p: String by Delegate()
}

委托模式的语法是val/var <property name>: <Type> by <expression>by后面的expression就是委托的部分,会将属性的get()set()委托给getValue()setValue()方法。

class Foo {
    private val delegate = Delegate()

    var p: String
        set(value: String) = delegate.setValue(..., value)
        get() = delegate.getValue(...)
}

委托属性不需要实现任何的接口,但是要提供getValue()方法(如果是var的话要提供setValue()方法),方法前加operator关键字。

下面是一个自定义的Delegate类:

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name} in $thisRef.'")
    }
}

当从委托属性p获取到Deletage的的实例时,DeletagegetValue就会被调用,getValue函数中的第一个参数就是p获取到的实例,第二个参数就是属性p

val e = Example()
println(e.p)

打印出来的内容是:

Example@33a17727, thank you for delegating ‘p’ to me!

由于pvar类型的,所有可以调用setValue函数,前两个参数与getValue参数一样,第三个就是要赋予的值:

e.p = "NEW"

这下打印出来的内容就是:

NEW has been assigned to ‘p’ in Example@33a17727.

注意:自 Kotlin1.1起可以在函数或代码块中声明一个委托属性,因此委托属性不一定是类的成员

委托标准

Kotlin的标准库中对于一些有用的委托提供了工厂(Factory)方法,这些接口在Kotlin标准库中声明。

interface ReadOnlyProperty<in R, out T> {
    operator fun getValue(thisRef: R, property: KProperty<*>): T
}

interface ReadWriteProperty<in R, T> {
    operator fun getValue(thisRef: R, property: KProperty<*>): T
    operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
}

延迟属性 Lazy

函数lazy()接收一个Lambdas表达式,然后并返回一个Lazy <T>的实例,它可以作为实现lazy属性的委托:第一次调用get()函数的时候会向执行Lambdas传递到lazy()函数,并且保存结果,后面调用的get()函数会直接返回报错的结果。

首先我们来看一个栗子,里面先不用到lazy,我们来看如何

fun loadName(person: Person): String {
    println("Load Name for ${person.name}")
    return person.name
}

fun loadAge(person: Person): Int {
    println("Load Age for ${person.age}")
    return person.age
}

class Person(val name: String, val age: Int) {
    private var _names: String? = null
    val newName: String
        get() {
            if (_names == null) {
                _names = loadName(this)
            }
            return _names!!
        }
    private var _ages: Int? = null
    val newAge: Int
        get() {
            if (_ages == null) {
                _ages = loadAge(this)
            }
            return _ages!!
        }
}

fun main(args: Array<String>) {
    val p = Person("Alice", 23)
    p.newName.println()
    p.newName.println()
}

首先先判断_names是否为空,然后通过一个方法,里面进行了一些操作,来赋予_names值,最后newName的值即为_names
打印的内容:

那么如果我们用lazy来代替这种写法会是什么样的呢?

fun loadName(person: Person): String { 
    /*代码与上面一样*/
}
fun loadAge(person: Person): Int { 
    /*代码与上面一样*/
}
class Person(val name: String) {
    val newName by lazy { loadName(this) }
    val newAge by lazy { loadAge(this) }
}

fun main(args: Array<String>) {
    /*代码与上面一样*/
}

打印出来的内容,和上面是一模一样的。

对比一下,当我们的属性越来越多,那么重复的代码也就越来越多,使用lazy省去了很多多余的代码。

默认地,对于lazy属性的计算是加了同步锁(synchronized) 的: 这个值只在一个线程被计算,并且所有的线程会看到相同的值。
如果要将同步锁关闭,可以多个线程同步执行,就加LazyThreadSafetyMode.PUBLICATION参数即可:

val lazyValue: String by lazy(LazyThreadSafetyMode.PUBLICATION) {
    println("computed!")
    "Hello"
}

如果要关掉线程安全配置,就加LazyThreadSafetyMode.NONE参数即可:

val lazyValue: String by lazy(LazyThreadSafetyMode.NONE) {
    println("computed!")
    "Hello"
}

可观察属性 Observable

Delegates.observable()有两个参数:初始化值和handler,每次对属性赋值操作,都会回调该handler方法(在属性赋值后执行),该方法里面有三个参数,分别是:被赋值的属性,旧值和新值。
举个例子:

import kotlin.properties.Delegates

class User {
    var name: String by Delegates.observable("<no name>") {
        prop, old, new ->
        println("$old -> $new")
    }
}

fun main(args: Array<String>) {
    val user = User()
    user.name = "first"
    user.name = "second"
}

User类中,<no name>就是初始化值,{}包住的代码块就是handler方法,pro, old, new就是该方法的三个参数,打印出来的内容为:

<no name> -> first
first -> second

如果需要拦截修改属性值动作并禁止修改,可以使用vetoable()取代observable()handler需要返回一个Booleantrue表示同意修改,false表示禁止修改,该回调会在属性值修改前调用。
将上面的例子里面的observable()修改为vetoable()后:

import kotlin.properties.Delegates

class User {
    var name: String by Delegates.vetoable("<no name>") {
        prop, old, new ->
        println("$old -> $new")
        false 
    }
}

fun main(args: Array<String>) {
    val user = User()
    user.name = "first"
    user.name = "second"
}

打印的结果是:

false

如果改为true,那就更observable()打印的一样了:

true

Map委托属性(Storing Properties in a Map)

可以用Map作为委托用于委托属性,多用于JSON解析上。

下面举个栗子,一个类里面有一个Map存放一些属性,通过setAttribute来设置这些属性:

class Person {
    private val _attributes = hashMapOf<String, String>()
    fun setAttribute(attrName: String, value: String) {
        _attributes[attrName] = value
    }
    // 获取键值为name的值
    val name: String
        get() = _attributes["name"]!!
    // 获取键值为company的值
    val company: String
        get() = _attributes["company"]!!
    // 获取键值为address的值
    val address: String
        get() = _attributes["address"]!!
    // 获取键值为email的值
    val email: String
        get() = _attributes["email"]!!
}

fun main(args: Array<String>) {
    val p = Person()
    val data = mapOf("name" to "Dmitry", "company" to "JetBrains")
    for ((attrName, value) in data)
        p.setAttribute(attrName, value)
    println(p.name) // 打印Dmitry
}

然后我们将这些属性委托给Map,再将代码简写一下

class Person2(private val attributes: Map<String, String>) {
    val name: String by  attributes
    val company: String by  attributes
    val address: String by  attributes
    val email: String by  attributes
}

fun main(args: Array<String>) {
    val data = mapOf("name" to "Dmitry", "company" to "JetBrains")
    val p = Person2(data)
    println(p.name) // Dmitry
}

同样对比,省去重复代码,我们来看一下生成的代码是什么样子的:

public final class Person2 {
   // $FF: synthetic field
   static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.property1(new PropertyReference1Impl(Reflection.getOrCreateKotlinClass(Person2.class), "name", "getName()Ljava/lang/String;")), (KProperty)Reflection.property1(new PropertyReference1Impl(Reflection.getOrCreateKotlinClass(Person2.class), "company", "getCompany()Ljava/lang/String;")), (KProperty)Reflection.property1(new PropertyReference1Impl(Reflection.getOrCreateKotlinClass(Person2.class), "address", "getAddress()Ljava/lang/String;")), (KProperty)Reflection.property1(new PropertyReference1Impl(Reflection.getOrCreateKotlinClass(Person2.class), "email", "getEmail()Ljava/lang/String;"))};
   @NotNull
   private final Map name$delegate;
   @NotNull
   private final Map company$delegate;
   @NotNull
   private final Map address$delegate;
   @NotNull
   private final Map email$delegate;
   private final Map attributes;

   @NotNull
   public final String getName() {
      Map var1 = this.name$delegate;
      KProperty var3 = $$delegatedProperties[0];
      return (String)MapsKt.getOrImplicitDefaultNullable(var1, var3.getName());
   }

   @NotNull
   public final String getCompany() {
      Map var1 = this.company$delegate;
      KProperty var3 = $$delegatedProperties[1];
      return (String)MapsKt.getOrImplicitDefaultNullable(var1, var3.getName());
   }

   @NotNull
   public final String getAddress() {
      Map var1 = this.address$delegate;
      KProperty var3 = $$delegatedProperties[2];
      return (String)MapsKt.getOrImplicitDefaultNullable(var1, var3.getName());
   }

   @NotNull
   public final String getEmail() {
      Map var1 = this.email$delegate;
      KProperty var3 = $$delegatedProperties[3];
      return (String)MapsKt.getOrImplicitDefaultNullable(var1, var3.getName());
   }

   public Person2(@NotNull Map attributes) {
      Intrinsics.checkParameterIsNotNull(attributes, "attributes");
      super();
      this.attributes = attributes;
      this.name$delegate = this.attributes;
      this.company$delegate = this.attributes;
      this.address$delegate = this.attributes;
      this.email$delegate = this.attributes;
   }
}

局部委托属性(1.1 起)

fun main(args: Array<String>) {
    example("localDelegate")
}

fun example(value: String) {
    val localDelegate by lazy {
        print("first ")
        value
    }
    localDelegate.println() // 打印first localDelegate
    localDelegate.println() // 打印localDelegate
}

现在,Kotlin支持局部委托属性。

委托属性要求

下面的代码是个委托类Delegate,里面有两个函数,一个是getValue函数,一个是setValue函数。

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name} in $thisRef.'")
    }
}

只读属性(read-only,使用val定义)

委托类需提供getValue函数,参数要求:
- thisRef:第一个参数,必须是属性对应的类或父类型。(上面的thisRef: Any?)
- property:第二个参数,必须是“KProperty<*>”或它的父类型(上面的property: KProperty<*>)。
- 函数返回类型必须跟属性同类型(或者子类型)。

可变属性(mutable,使用var定义)

委托类需提供getValue函数和setValue函数,参数要求:
- thisRef:第一个参数,同getValue对应的参数
- property:第二个参数,同getValue对应的参数
- 新增(new value):第三个参数,类型必须跟属性一样或其父类型。

getValue()setValue()函数可以作为委托类的成员函数或者扩展函数来使用。 当需要委托一个属性给一个不是原来就提供这些函数的对象的时候,后者更为方便。

两种函数都需要用operator关键字修饰。

接口

委托类可以实现ReadOnlyProperyReadWriteProperty接口中的带operator的方法,这些接口在Kotlin标准库中声明:

interface ReadOnlyProperty<in R, out T> {
    operator fun getValue(thisRef: R, property: KProperty<*>): T
}

interface ReadWriteProperty<in R, T> {
    operator fun getValue(thisRef: R, property: KProperty<*>): T
    operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
}

提供委托(自 1.1 起)

provideDelegate为提供委托,它可以为属性提供对象委托逻辑,可能的使用场景是在创建属性时(而不仅在其 gettersetter 中)检查属性一致性。
provideDelegate 的参数与 getValue 相同:
- thisRef —— 必须与属性所有者类型(对于扩展属性——指被扩展的类型)相同或者是它的超类型。
- property —— 必须是类型 KProperty<*> 或其超类。

例如,在绑定之前检查属性名称:

class ResourceLoader(resId: ResourceID) {
    operator fun provideDelegate(thisRef: MyUI, prop: KProperty<*>): ReadOnlyProperty<MyUI, String> {
        checkProperty(thisRef, prop.name)
        // 创建委托
    }
    private fun checkProperty(thisRef: MyUI, name: String) {
    }
}
fun MyUI.bindResource(id: ResourceID): ResourceLoader {
    return ResourceLoader(id)
}
class MyUI {
    val image by bindResource(ResourceID.image_id) //bindResource()产生委托对象
    val text by bindResource(ResourceID.text_id)
}

在创建 MyUI 实例期间,为每个属性调用provideDelegate方法,并立即执行必要的验证。

如果没有这种拦截属性与其委托之间的绑定的能力,为了实现相同的功能, 你必须显式传递属性名:

class MyUI {
    val image by bindResource(ResourceID.image_id, "image")
    val text by bindResource(ResourceID.text_id, "text")
}
fun <T> MyUI.bindResource(
    id: ResourceID<T>,
    propertyName: String
    ): ReadOnlyProperty<MyUI, T> {
        checkProperty(this, propertyName)
        // 创建委托
}

由于暂时没用的这个提供委托,所以在这里也不过多的介绍,上面是官网的一个栗子。

一个委托实例

下面来看一个自定义的Delegate,用来访问SharedPreference,这段代码是Kotlin for Android Developer的示例:

class Preference<T>(val context: Context, val name: String, val default: T) : ReadWriteProperty<Any?, T> {

    val prefs by lazy { context.getSharedPreferences("default", Context.MODE_PRIVATE) }

    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return findPreference(name, default)
    }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        putPreference(name, value)
    }

    private fun <U> findPreference(name: String, default: U): U = with(prefs) {
        val res: Any = when (default) {
            is Long -> getLong(name, default)
            is String -> getString(name, default)
            is Int -> getInt(name, default)
            is Boolean -> getBoolean(name, default)
            is Float -> getFloat(name, default)
            else -> throw IllegalArgumentException("This type can be saved into Preferences")
        }

        res as U
    }

    private fun <U> putPreference(name: String, value: U) = with(prefs.edit()) {
        when (value) {
            is Long -> putLong(name, value)
            is String -> putString(name, value)
            is Int -> putInt(name, value)
            is Boolean -> putBoolean(name, value)
            is Float -> putFloat(name, value)
            else -> throw IllegalArgumentException("This type can be saved into Preferences")
        }.apply()
    }
}

使用的时候:

class ExampleActivity : AppCompatActivity(){
    var a: Int by Preference(this, "a", 0)

    fun whatever(){
        println(a)//会从SharedPreference取这个数据
        aInt = 9 //会将这个数据写入SharedPreference
    }
}

这样就很方便了,再也不用去重复写getSharedPreference()commit()edit()apply()之类的东西了。

作者:u011976726 发表于2017/11/26 20:50:10 原文链接
阅读:157 评论:0 查看评论

二维dp 之 完美序列

$
0
0

来源:中国石油大学训练平台

4874: 完美序列

时间限制: 1 Sec  内存限制: 128 MB
提交: 28  解决: 17
[提交][状态][讨论版]

题目描述

已知一个长度为l的序列:b1,b2,b3,…,bl (1<=b1<=b2<=b3<=…<=bl<=n)。若这个序列满足每个元素是它后续元素的因子,换句话说就是对于任意的i (2<=i<=l)都满足bi%bi-1=0 (其中“%”代表求余),则称这个序列是完美的。你的任务是对于给定的n和l,计算出一共有多少序列是完美序列。由于答案很大,所有输出答案对1000000007取余后的结果。

输入

输入的第一行为一个正整数T (T<=1000),代表一共有T组测试数据。

每组测试数据包含两个正整数n,l (1<=n, l<=2000),分别代表序列中元素大小的最大值和序列的长度。

输出

对于每组测试数据,输出一行包含一个整数,代表答案对1000000007取余后的结果。

样例输入

33 26 42 1

样例输出

5392
【分析】:

根据题意推得,可以打出一张表格,输入n,l直接询问。

用dp[i][j]表示长度为i时,以数字j结尾的,序列数量

状态方程:dp[i][j] = sum ( dp[i-1][k] ) ,sum()的意思是累加所有的dp[i-1][k],其中k是j的因子。

初态:dp[1][j]=1,长度为1时的数量

根据初态,递推打出2000*2000的表格。

当输入n,l时,只需把第n行前l项累加即可

【代码】:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll dp[2020][2020];
int T,n,m;
int main()
{
    for(int i=1;i<=2002;i++)dp[1][i]=1;
    for(int i=2;i<=2002;i++)//长度
    {
        for(int j=1;j<=2002;j++)
            for(int k=1;k*j<=2002;k++)
            {
                dp[i][j*k]+=dp[i-1][j];
                dp[i][j*k]%=mod;
            }
    }
    for(int i=1;i<=2002;i++)
    {
        for(int j=2;j<=2002;j++)
        {
            dp[i][j]+=dp[i][j-1];
            dp[i][j]%=mod;
        }
    }
    /*for(int i=1;i<=8;i++)
    {
        printf("i = %d  ",i);
        for(int j=1;j<=8;j++)
            printf("%6lld",dp[i][j]);
        puts("");
    }*/
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        cout<<dp[m][n]<<endl;
    }
}
 
/**************************************************************
    Problem: 4874
    User: summer17083
    Language: C++
    Result: 正确
    Time:932 ms
    Memory:33576 kb
****************************************************************/


作者:winter2121 发表于2017/11/26 20:56:19 原文链接
阅读:35 评论:0 查看评论

【莫比乌斯反演】BZOJ2820 YY的GCD

$
0
0

题面在这里

这道题类似。

先考虑枚举质数p,答案就是:

pdμ(d)npdmpd

T=pd,考虑枚举T,则有:
Tmin{n,m}nTmTp|Tμ(Tp)

如果能够预处理p|Tμ(Tp)关于T的前缀和,前面的柿子就可以O(n)求解

其实直接暴枚p就好了

因为均摊每个质数是ln(n)的,而质数的个数是nln(n)

所以预处理是O(n)

示例程序:

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;

const int maxn=10000005;
int tst,n,m,p[maxn],mu[maxn],t[maxn];
ll sum[maxn];
bool vis[maxn];
void get_mu(){
    int n=10000000;mu[1]=1;
    for (int i=2;i<=n;i++){
        if (!vis[i]) p[++p[0]]=i,mu[i]=-1;
        for (int j=1;j<=p[j]&&i*p[j]<=n;j++){
            vis[i*p[j]]=1;
            if (i%p[j]==0) {mu[i*p[j]]=0;break;}
             else mu[i*p[j]]=-mu[i];
        }
    }
    for (int i=1;i<=p[0];i++)
     for (int j=1;p[i]*j<=n;j++) t[p[i]*j]+=mu[j];
    for (int i=1;i<=n;i++) sum[i]=sum[i-1]+t[i];
}
ll get(int n,int m){
    if (n>m) swap(n,m);
    ll res=0;
    for (int T=1,lst=0;T<=n;T=lst+1){
        lst=min(n/(n/T),m/(m/T));
        res+=(sum[lst]-sum[T-1])*(n/T)*(m/T);
    }
    return res;
}
int main(){
    scanf("%d",&tst);get_mu();
    while (tst--){
        scanf("%d%d",&n,&m);
        printf("%lld\n",get(n,m));
    }
    return 0;
}
作者:linkfqy 发表于2017/11/26 20:57:21 原文链接
阅读:30 评论:0 查看评论

Netty网络聊天室之优雅的JavaFX界面开发

$
0
0

Java在服务端领域能够独占鳌头,然而,在客户端领域一直不温不火。Java的客户端技术,从AWT,SWING,SWT,一直到JAVAFX,即使每一代都有非常大的改善,但仍改变不了它尴尬的地位。依我看来,使用JAVA来开发桌面应用,大概只有我有我们这批javaer了偷笑

不管怎样,javafx的设计理念还是非常优秀的。它借鉴了html开发的特点,将代码,界面,样式三者分离。使用java代码来控制逻辑,使用xml来设计界面,使用css来控制样式。

本文将使用一个简单的例子,来演示javafx的开发案例。

开发工具

e(fx)eclipse是一个带有javafx开发插件的eclipse版本,它自带css,xml代码自动补全。
JavaFX Scene Builder 2.0是一个javafx界面开发的辅助工具,其实就是支持你使用拖曳的方式来设计界面。对于调整界面位置非常有用。

界面样式逻辑三权分立

有了efxeclipse,我们就可以来开发我们的javafx项目啦。
登录界面控件非常少,可以拿来作为入门例子。
在javafx里,Stage表示一个有用户界面的应用程度窗口,在Stage下面,则是由Scene来表示界面容器。Scene包含所有界面组件,例如各种ui控件和ui子容器。
类似于Flex开发,我们的javafx界面设计是写在fxml文件里。如下:
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.chart.*?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity"
	minHeight="-Infinity" minWidth="-Infinity" prefHeight="330.0"
	prefWidth="430.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
	fx:controller="com.kingston.ui.controller.LoginViewController"
	stylesheets="@../css/login.css">
	<children>
		<ImageView fitHeight="330.0" fitWidth="430.0" layoutX="91.0"
			layoutY="90.0" pickOnBounds="true" preserveRatio="true"
			AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
			AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
			<image>
				<Image url="@../img/login.png" />
			</image>
		</ImageView>
		<Button fx:id="login" layoutX="135.0" layoutY="288.0"
			mnemonicParsing="false" onMouseClicked="#login" onMouseEntered="#login_en"
			onMouseExited="#login_ex" prefHeight="32.0" prefWidth="194.0" text="%login.safeLogin"
			textFill="WHITE">
			<font>
				<Font size="18.0" />
			</font>
		</Button>
		<ImageView fitHeight="80.0" fitWidth="80.0" layoutX="38.0"
			layoutY="195.0" pickOnBounds="true" preserveRatio="true">
			<image>
				<Image url="@../img/head.jpg" />
			</image>
		</ImageView>
		<TextField fx:id="userId" layoutX="135.0" layoutY="195.0"
			prefHeight="25.0" prefWidth="194.0" promptText="%login.account" text="1000" />
		<PasswordField fx:id="password" layoutX="135.0" layoutY="226.0"
			prefHeight="25.0" prefWidth="194.0" promptText="%login.password" />
		<CheckBox fx:id="rememberPsw" layoutX="135.0" layoutY="258.0"
			mnemonicParsing="false" text="%login.rememberPsw" />
		<CheckBox fx:id="autoLogin" layoutX="260.0" layoutY="258.0"
			mnemonicParsing="false" text="%login.autoLogin" />
		<Label />
		<Label />
		<ImageView fx:id="closeBtn" fitHeight="30.0" fitWidth="30.0"
			layoutX="399.0" onMouseClicked="#close" onMouseEntered="#closeEntered"
			onMouseExited="#closeExited" pickOnBounds="true" preserveRatio="true"
			AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
			<image>
				<Image url="@../img/close.png" />
			</image>
			<rotationAxis>
				<Point3D />
			</rotationAxis>
		</ImageView>
		<ImageView fx:id="minBtn" fitHeight="30.0" fitWidth="30.0"
			layoutX="346.0" onMouseClicked="#min" onMouseEntered="#minEntered"
			onMouseExited="#minExited" pickOnBounds="true" preserveRatio="true"
			AnchorPane.rightAnchor="30.0" AnchorPane.topAnchor="0.0">
			<image>
				<Image url="@../img/min.png" />
			</image>
		</ImageView>
		<ProgressBar layoutX="132.0" layoutY="289.0" prefHeight="32.0" fx:id="loginProgress"
			prefWidth="200.0" visible="false" />
		<Pane fx:id="errorPane" layoutY="36.0" prefHeight="307.0"
			prefWidth="430.0" style="-fx-background-color: #9AD3EE;" visible="false"
			AnchorPane.topAnchor="30.0">
			<children>
				<Label fx:id="errorTips" layoutX="118.0" layoutY="52.0" prefHeight="153.0"
					prefWidth="194.0" wrapText="true">
					<font>
						<Font size="27.0" />
					</font>
				</Label>
				<Button layoutX="118.0" layoutY="223.0" mnemonicParsing="false"
					onMouseClicked="#backToLogin" prefHeight="32.0" prefWidth="194.0"
					style="-fx-background-color: #09A3DC;" text="%login.backToLogin" textFill="WHITE">
					<font>
						<Font size="18.0" />
					</font>
				</Button>
			</children>
		</Pane>
		<Hyperlink layoutX="339.0" layoutY="195.0" text="%login.registerAccount"
			onMouseClicked="#gotoRegister">
			<font>
				<Font size="14.0" />
			</font>
		</Hyperlink>
		<Hyperlink layoutX="339.0" layoutY="226.0" text="%login.findPsw">
			<font>
				<Font size="14.0" />
			</font>
		</Hyperlink>
	</children>

</AnchorPane>
fxml里面有各种id定义,有了这些id,我们就可以用java代码对其进行控制。在fxml里,有一个fx:controller元素就是用来定义对应的控制器的。
public class LoginViewController implements ControlledStage, Initializable {

	@FXML
	private Button login;
	@FXML
	private TextField userId;
	@FXML
	private PasswordField password;
	@FXML
	private CheckBox rememberPsw;
	@FXML
	private CheckBox autoLogin;
	@FXML
	private ImageView closeBtn;

	@FXML
	private void login() throws IOException {
		final long useId = Long.parseLong(userId.getText());
		final String psw = password.getText();

		if (!IoBaseService.INSTANCE.isConnectedSever()) {
			errorPane.setVisible(true);
			errorTips.setText(I18n.get("login.failToConnect"));
			return;
		}

		loginProgress.setVisible(true);
		login.setVisible(false);

		LoginManager.getInstance().beginToLogin(useId, psw);
	}
}
类似于LoginViewController里,如果我们需要控制xml里面的控件,我们就需要在代码里对控件类型写上@FXML的注解,变量的名字就是fxml里的id了。同时,控件的各种触发事件,例如点击,滑动事件,也需要写上@FXML注解,方法名称也要跟fxml文件里的命名一样,例如 onMouseClicked="#login"。
类似于html的css文件,我们的ui控件样式最好也是写在独立的css文件,然后通过fxml进行指向,例如: stylesheets="@../css/login.css"。
在这里有个需要特别注意的是,如果代码需要更新ui显示,我们必须要在javafx的ui线程上进行
/**
	 * 将任务转移给fxapplication线程延迟执行
	 * @param task
	 */
	public void runTaskInFxThread(Runnable task){
		Platform.runLater(task);
	}

文字资源的国际化支持

客户端开发程序,我们就不可避免地要进行国际化支持,对不同的国际地区显示不同的文字。javafx在这方面也做得不错。
在加载fxml的时候,我们可以指定国际化资源文件,如下 
URL url = Thread.currentThread().getContextClassLoader().getResource(resource);
			FXMLLoader loader = new FXMLLoader(url);
			loader.setResources(ResourceBundle.getBundle("i18n/message"));
这样,fxml就可以使用 text="%login.rememberPsw"  的方式引入国际化资源了。
在非fxml文件里使用国际化文字的方式。定义一个加载使用国际化文字的工具类(I18n.java)
/**
 * 国际化资源池
 * @author kingston
 */
public class I18n {

    private static ResourceBundle resourcePool;

    static {
        try {
            resourcePool = ResourceBundle.getBundle("i18n/message");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String get(String key, Object... args) {
        if (!resourcePool.containsKey(key)) {
           return "国际化资源不存在";
        }
        String message = resourcePool.getString(key);
        if (args != null) {
            return MessageFormat.format(message, args);
        } else {
            return message;
        }
    }
}
在代码里,使用 I18n.get("register.operateSucc") 即可。
 

统一管理Stage的加载与切换

在JAVAFX里,经常需要在不同的stage进行切换。为了能高效统一管理stage,我们可以将全部stage缓存起来,根据需要动态显示隐藏窗口。
public class StageController {

	private Map<String, Stage> stages = new HashMap<>();

	private Map<String, ControlledStage> controllers = new HashMap<>();

	public void addStage(String name, Stage stage) {
		this.stages.put(name, stage);
	}

	public Stage getStageBy(String name) {
		return this.stages.get(name);
	}

	public void setPrimaryStage(String name, Stage stage) {
		this.addStage(name, stage);
	}

	public Stage loadStage(String name, String resource, StageStyle... styles) {
		Stage result = null;
		try{
			URL url = Thread.currentThread().getContextClassLoader().getResource(resource);
			FXMLLoader loader = new FXMLLoader(url);
			loader.setResources(ResourceBundle.getBundle("i18n/message"));
			Pane tmpPane = (Pane)loader.load();
			ControlledStage controlledStage = (ControlledStage)loader.getController();
			this.controllers.put(name, controlledStage);
			Scene tmpScene = new Scene(tmpPane);
			result = new Stage();
			result.setScene(tmpScene);

			for (StageStyle style:styles) {
				result.initStyle(style);
			}
			this.addStage(name, result);
		}catch(Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	@SuppressWarnings("unchecked")
	public <T> T load(String resource, Class<T> clazz) {
		try{
			URL url = Thread.currentThread().getContextClassLoader().getResource(resource);
			FXMLLoader loader = new FXMLLoader(url);
			return (T)loader.load();
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	public <T> T load(String resource, Class<T> clazz, ResourceBundle resources) {
		try{
			URL url = Thread.currentThread().getContextClassLoader().getResource(resource);
			return (T)FXMLLoader.load(url, resources);
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}

	public Stage setStage(String name) {
		Stage stage = this.getStageBy(name);
		if (stage == null) {
			return null;
		}
		stage.show();
		return stage;
	}

	public boolean switchStage(String toShow, String toClose) {
		getStageBy(toClose).close();
		setStage(toShow);

		return true;
	}

	public void closeStge(String name) {
		Stage target = getStageBy(name);
		target.close();
	}

	public boolean unloadStage(String name) {
		return this.stages.remove(name) != null;
	}

	public ControlledStage getController(String name) {
		return this.controllers.get(name);
	}

}


全部代码已在github上托管

服务端代码请移步 --> netty聊天室服务器

客户端代码请移步 --> netty聊天室客户端





作者:littleschemer 发表于2017/11/26 21:04:02 原文链接
阅读:36 评论:0 查看评论

[左偏树]BZOJ 2809——[Apio2012]dispatching

$
0
0

题目描述

在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为 Master。除了 Master以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者 支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者 发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递 人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,就不需要支付管理者的薪水。你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。写一个程序,给定每一个忍者i的上级Bi,薪水Ci,领导力L i,以及支付给*忍者们的薪水总预算M,输出在预算内满足上述要求时顾客满意度的最大值。

1 ≤N ≤ 100,000 忍者的个数;

1 ≤M ≤ 1,000,000,000 薪水总预算;

0 ≤Bi < i 忍者的上级的编号;

1 ≤Ci ≤ M 忍者的薪水;

解题思路

不想说什么,很明显的左偏树。

从叶子节点往根上合并,如果堆内元素和大于M就把最大的数丢掉。

1 ≤Ci ≤ M 这个条件保证堆不为空真棒。

#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
inline int _read(){
    int num=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') num=num*10+ch-48,ch=getchar();
    return num;
}
const int maxn=100005;
struct jz{
    jz* son[2];
    int s,w;
    LL x;
}*rt[maxn],t[maxn],*null=t,*len=t;
jz* newnode(int x){
    len++;len->x=len->w=x;len->s=1;
    len->son[0]=len->son[1]=null;
    return len;
}
int tot,son[2*maxn],nxt[2*maxn],lnk[maxn];
int n,m,L[maxn],gen;
LL ans;
void add(int x,int y){nxt[++tot]=lnk[x];lnk[x]=tot;son[tot]=y;}
jz* merge(jz* x,jz* y){
    if (x->w < y->w) swap(x,y);
    if (y==null) return x;
    x->son[1]=merge(x->son[1],y);
    if (x->son[1]->s > x->son[0]->s) swap(x->son[1],x->son[0]);
    x->s=x->son[0]->s + x->son[1]->s +1;
    x->x=x->son[0]->x + x->son[1]->x +x->w;
    return x;
}
void DFS(int x,int fa){
    for (int j=lnk[x];j;j=nxt[j]) if (son[j]!=fa) DFS(son[j],x),rt[x]=merge(rt[x],rt[son[j]]);
    while(rt[x]->x >m) rt[x]=merge(rt[x]->son[1],rt[x]->son[0]);
    ans=max(ans,(LL)rt[x]->s*L[x]);
}
int main(){
    freopen("exam.in","r",stdin);
    freopen("exam.out","w",stdout);
    n=_read();m=_read();
    for (int i=1;i<=n;i++){
        int x=_read(),c=_read();L[i]=_read();
        if (x) add(i,x),add(x,i);else gen=i;
        rt[i]=newnode(c);
    }
    DFS(gen,0);
    printf("%lld\n",ans);
    return 0;
}
作者:CHN_JZ 发表于2017/11/26 21:06:41 原文链接
阅读:35 评论:0 查看评论

[主席树]BZOJ 3524——[Poi2014]Couriers

$
0
0

题目描述

给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。

解题思路

直接上主席树。

构造权值线段树,询问时不停遍历节点数最多的一边就可以了。

但是要注意:最后停下的节点并不是出现次数最多的节点

但对于这道题,如果有解这种方法一定正确。

#include<cstdio>
using namespace std;
const int maxn=500005,maxm=22000005;
inline int _read(){
    int num=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') num=num*10+ch-48,ch=getchar();
    return num;
}
struct jz{
    jz* son[2];
    int L,R,x;
};
jz *rt[maxn],t[maxm],*null=t,*len=t;
jz* newnode(int L,int R,int num){
    len++;len->L=L,len->R=R;len->x=num;
    len->son[0]=len->son[1]=null;
    return len;
}
jz* Build(int L,int R){
    jz* p=newnode(L,R,0);
    if (L==R) return p;
    int mid=L+(R-L>>1);
    p->son[0]=Build(L,mid);
    p->son[1]=Build(mid+1,R);
    return p;
}
jz* Insert(jz* k,int x){
    jz* p=newnode(k->L,k->R,k->x);
    p->son[0]=k->son[0];p->son[1]=k->son[1];
    if (p->L==p->R){p->x++;return p;}
    int mid=p->L+(p->R-p->L>>1);
    if (x<=mid) p->son[0]=Insert(p->son[0],x);
    else        p->son[1]=Insert(p->son[1],x);
    p->x=p->son[0]->x+p->son[1]->x;
    return p;
}
int n,m,a[maxn],tot;
int query(jz* k,jz* p,int w){
    if (k->L==k->R){if ((k->x-p->x)*2>w) return k->L;else return 0;}
    if (k->son[0]->x - p->son[0]->x > k->son[1]->x - p->son[1]->x) return query(k->son[0],p->son[0],w);else query(k->son[1],p->son[1],w);
}
int main(){
    freopen("exam.in","r",stdin);
    freopen("exam.out","w",stdout);
    n=_read();m=_read();
    for (int i=1;i<=n;i++) a[i]=_read();
    rt[0]=Build(1,n);
    for (int i=1;i<=n;i++) rt[i]=Insert(rt[i-1],a[i]);
    for (int i=1;i<=m;i++){
        int x=_read(),y=_read();
        printf("%d\n",query(rt[y],rt[x-1],y-x+1));
    }
    return 0;
}
作者:CHN_JZ 发表于2017/11/26 21:12:57 原文链接
阅读:34 评论:0 查看评论

linux vim编辑器之块选择

$
0
0

vim块选择
V: 字符选择,会把光标经过的位置反白选择
v: 行选择,会把光标经过的行反白选择
Ctrl + v: 块选择,可以使用长方形的方式反白选择内容
y: 将反白的地方复制
d: 将反白的地方删除

其中V或者v来选择内容都可以使用鼠标来完成,至于块选择就比就特殊了。

看下图,我可以使用Ctrl+v来选择图中矩形反白的部分,可以按y进行复制,或者按d删除。这个矩形选中对于文件排版很有帮助。

这里写图片描述

作者:u012062455 发表于2017/11/26 21:18:15 原文链接
阅读:5 评论:0 查看评论

两序列相乘的第k大元素

$
0
0

4875: 第k大数

时间限制: 10 Sec  内存限制: 128 MB
提交: 63  解决: 21
[提交][状态][讨论版]

题目描述

有两个序列a,b,它们的长度分别为n和m,那么将两个序列中的元素对应相乘后得到的n*m个元素从大到小排列后的第k个元素是什么?

输入

输入的第一行为一个正整数T (T<=10),代表一共有T组测试数据。

每组测试数据的第一行有三个正整数n,m和k(1<=n, m<=100000,1<=k<=n*m),分别代表a序列的长度,b序列的长度,以及所求元素的下标。第二行为n个正整数代表序列a。第三行为m个正整数代表序列b。序列中所有元素的大小满足[1,100000]。

输出

对于每组测试数据,输出一行包含一个整数代表第k大的元素是多少。

样例输入

33 2 31 2 31 22 2 11 11 12 2 41 11 1

样例输出

311

【分析】:直接求解很明显数据量太大。

二分枚举。

相乘后的新序列的最大值和最小值很容易得出,然后对这个区间进行二分枚举。

有点像猜数。

对每次猜的数x,求一下有多少个数比x大,直到猜的数恰好有k个数比x大,计算结束。


如何求比x大的数有多少个:

序列a,b都按从大到小排序

设两个下标i=0,j=m-1分别跑a和b;

看代码中的函数 f( ll x ) 就能看懂。

【代码】:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,k,T;
ll a[101010],b[101010];
bool cmp(ll c,ll d)
{
    return c>d;
}
ll f(ll x)//统计>=x的数量
{
    ll c=0,j=m-1;
    for(int i=0;i<n;i++)
    {
        while(j&&a[i]*b[j]<x)j--;
        if(a[i]*b[j]>=x)c+=j+1;
    }
    return c;
}
int main()
{
    cin>>T;
    while(T--)
    {
        cin>>n>>m>>k;
        for(int i=0;i<n;i++) scanf("%lld",&a[i]);
        for(int i=0;i<m;i++) scanf("%lld",&b[i]);
        sort(a,a+n,cmp);
        sort(b,b+m,cmp);
        ll mid,r=a[0]*b[0],l=a[n-1]*b[m-1];
        while(l<r)
        {
            mid=(l+r)/2;
            if(f(mid)>=k)
                l=mid+1;
            else r=mid;
        }
        if(f(l)<k)l--;//测试发现有时少1,干脆特判了一下...
        cout<<l<<endl;
    }
}
/**************************************************************
    Problem: 4875
    User: summer17083
    Language: C++
    Result: 正确
    Time:1192 ms
    Memory:3280 kb
****************************************************************/


作者:winter2121 发表于2017/11/26 21:21:56 原文链接
阅读:29 评论:0 查看评论

模糊图像退化与去模糊的数学模型

$
0
0

一 图像退化模型
建立图像的退化模型即是将图像的降质的机理用数学的方式描述出来,这也是图像去模糊成功的重要因素。通常来说,图像的退化可以概括为初始的输入图像f(x,y),经过退化函数k(x,y)作用后,再附加上随机噪声n(x,y),最后输出为模糊图像g(x,y)
用数学形式描述为:

g(x,y)=k(x,y)f(x,y)+n(x,y)

在上述退化模型确定以后,使用该模型去模糊的过程就是在模糊图像的基础g(x,y)上,通过一定方法寻求合理的退化函数k(x,y),然后利用一定的策略求解退化的逆问题,进而获得真实图像f(x,y)的尽可能高程度的近似版本。
若忽略噪声的干扰,即令n(x,y)=0,假设退化函数是空间不变的,模型简化为:
g(x,y)=kf(x,y)

图像连续退化模型,根据傅里叶变换原理转换到频域:
G(u,v)=K(u,v)F(u,v)+N(u,v)

二 图像去模糊的概率模型
通常去模糊算法的一个自然的出发点就是首先从概率的角度出发建立去模糊问题对应的方程。假设我们已经获知降质过程中干扰图像的噪声类型,我们就能够很容易的写出模糊图像的似然p(g|f,k),即g关于f,k的条件概率密度。根据概率知识,我们可以从最大化该条件概率出发,寻求最为合适的f,k,但是因图像退化时引起信息损失进而导致去模糊问题的严重不适定性,如果仅仅最大化这个似然模型则容易导致结果中包含较多的振铃效应,并且噪声也被进一步放大。
人们通常会在去模糊过程中加如一些约束。利用一些关于清晰图的先验知识,根据贝叶斯理论,我们能够构建出关于未知量的后验分布:
p(f,k|g)p(g|f,k)p(k)p(f)

如果模糊核已知条件下:
p(f,k|g)p(g|f,k))p(f)

其中关于未知量的先验知识p(x)p(f)是人工定义的或者从样本数据学习得到的。把关于未知量的先验知识结合到图像去模糊模型中能够克服单从模糊图像的似然估计fk时的不稳定性,改善未知量估计的质量。
最大后验(MAP)方法
如果模糊核提前获知,则求解出的清晰图像为:
f^=argmaxfp(f|g,k)

模糊核未知条件下,需要在反求清晰图像的过程中求解模糊核:
{f^,k^}=argmaxf,kp(f,k|g)

处理上式中模型的典型手段是首先将求取概率的最大转变成求取能的最小,将后验分布改写为吉布斯分布的形式:
p(f,k|g)=1Zexp(1TU(f,k))

其中是一个Ug决定的能量方程,z为归一化常数由此可知,能够最大化后验概率的图像f和核k同时也是使得式的值达到最小的变量。根据U(f,k)logp(f,k|g)+C,C代表任意常数,于是我们可以得出后验分布对MAP应的问题:
minf,kF(g;k,f)+αρf(f)+βρk(k)

其中方程F对应着似然项的负对数,用于惩罚清晰图像和模糊核卷积结果与观察数据之间的差异,我们称之为数据项。而方程ρfρk对应着先验项的负对数,分别用于惩罚清晰图像和模糊核以使它们服从先验知识,我们称之为正则项。
由于图像中通常包含很多像素点,于是求解整幅图像的MAP问题将有一个非常大的解空间,这也是MAP方法遇到的要问题,能量方程可能是个非凸的问题,在这种情况下一般不可能达到全局最优解;受校糊图像中未知噪声的影响,人们通常要谨慎的选择正则项的权重。
噪声模型有高斯噪声,泊松噪声,均匀分布噪声等。

自然图像的先验知识
早期文献关注自然图像的振幅谱,认为自然图像振幅谱在一定条件下近似服从一个能量定律;也有人则指出清晰图像的熵高于模糊图像。

近几年来的工作主耍关注清晰图像对滤波算子响应结果的分布情况

假设清晰图像中所有像素点的导数之间彼此扣独立并服从一种零平均的高斯尺度混合型(GSM),也有人提出梯度符合超拉普拉斯分布(看另外一篇博客)

模糊核先验知识
首先图像的形成过程就是光子在传感器上不断累积的过程,因此模糊核中的所有元素都是非负的,即其次,更为重要的一点是模糊核通常是稀疏的,也即包含相对少量的非零元素。模糊核的这种非负稀疏特点被之前的图像去模糊方法广泛地使用。

三 单幅图像去模糊
传统的从单幅图像出发盲去除模糊的算法一般以fk的后验分布为出发点:

p(f,k|g)p(g|f,k)p(k)p(f)

通常假设噪声为均勾的高斯噪声于是其中的似然项描述为:
p(g|f,k)iexp(((fk)igi)22σ2)

其中σ是噪声的标准差,p(f)p(k)分别对应着清晰图像和校糊核的先验约束。
模糊核估计
Cho[1]为了更新模糊核,和首先对当前估计的清晰图像进行滤波处理以预测阶梯边界。通过双边滤波滤除大部分的噪声,接着采用冲击滤波来增强锐利的边缘,得到图像,紧接着求得该图像x,y方向的导数,最后根据一定标准舍弃其中较小的值以获得稀疏的梯度图pxpy
在从清晰图像预测和保留显著边缘以后,结合稀疏的导数图像的更高阶信息形成新的集合{pq={px,py,dxpx,12(dxpy+dypx),dypy}
用来估计模糊核:
minkqwq||kpqdqg||22+β||k||22

其中dq{dx,dy,dxx,dxy,dyy},β为正则项的权重,wq分别对应着不同的偏导数。这是一个简单的线性最小二乘问题,容易在频域求得其解:
k^=F1(qwqF(pq)¯¯¯¯¯¯¯¯F(gq)qwqF(pq)¯¯¯¯¯¯¯¯F(pq)+β)

在获得模糊核k^之后,对其进行阈值化处理,即将其中值小于最大元素值1/20的的元素置为0。这就保证了其中所有元素之为非负,且加强了模糊核的稀疏性。
jia[2].增加了滤波处理步骤。
shan[3]相对于前两中方法 ,不对图像进行任何滤波处理,直接使用l1范数代替正则项。
minkqwq||kpqdqg||22+β||k||1

清晰图像估计
在清晰图像估计阶段,使用当前得到的k^来对模糊图像执行去除模糊操作以更新当前的清晰图像。[1]使用的去卷积模型为:
minfqwq||k^dqfdqg||22+α||dxf||22+α||dyf||22

中为正则项的权重,而此时的偏导数包括了零阶导在内:dq{dx,dy,dxx,dxy,dyy}观察可知,在这个问题中,数据项中包括了图像的高阶导数,而正则项中则没有,我们可以在频域里求得其标准解。
[2]选择增加l2正则项来促进清晰图像的梯度接近于前次迭代中预测的稀疏导数图
minfqwq||k^dqfdqg||22+α||dxfpx||22+α||dyfpy||22

由于本校型促使锐化边缘出现在{pq}中对应的位置,因而降低了由于使用l2正则项而带来的过平滑问题,同时本模型也同样可以在频域范围内得到标准解。

利用噪声模糊图像盲去模糊
yuan[4]提出了一种新的盲去模糊方法,该方法使用了观察的模糊图像和同一场景中的一幅锐化但是包含噪声的图像。模糊图像是在弱光照条件下长时间光的情况下出现的,而如果在此时给定一个高的设置而同时减少曝光时间则可以获得同一场景的锐化但是包含噪声的图像。虽然得到的噪声图像可能退化的比较严重,以至于不能通过直接的去噪理得到一幅清晰的图像,但是可以将其作为清晰图像的初始值来估计模糊核。除此之外,如果得到模糊核以后,同样能够利用噪声图像来指导最终的非盲去模糊操作,在此阶段文中采用了一种改进RL的算法,并使用噪声图像fN来抑制结果中的振铃效应。

[1].Cho S, Lee S. Fast motion deblurring[C]//ACM Transactions on Graphics (TOG). ACM, 2009, 28(5): 145.
[2].Xu L, Jia J. Two-phase kernel estimation for robust motion deblurring[C]//European Conference on Computer Vision. Springer, Berlin, Heidelberg, 2010: 157-170.
[3].Shan Q, Jia J, Agarwala A. High-quality motion deblurring from a single image[C]//Acm transactions on graphics (tog). ACM, 2008, 27(3): 73.
[4].Yuan L, Sun J, Quan L, et al. Image deblurring with blurred/noisy image pairs[C]//ACM Transactions on Graphics (TOG). ACM, 2007, 26(3): 1.

本文节选自《单幅运动模糊图像的盲去卷积》李新刚 本博客仅为阅读方便,权利归原作者所有。

作者:yuyangyg 发表于2017/11/26 21:31:47 原文链接
阅读:21 评论:0 查看评论

一起Talk Android吧(第五十二回:Android中的Fragment交互续)

$
0
0

各位看官们,大家好,上一回中咱们说的是Android中Fragment的例子,这一回咱们继续说该例子。闲话休提,言归正转。让我们一起Talk Android吧!


看官们,我们在前面章回中介绍过Fragment的交互,只不过在中间插入了嵌套Fragment相关的知识,大家可能有点忘记了,其实这也是为继续介绍Fragment做铺垫。在此铺垫之上我们将继续介绍Fragment的交互。不过我们这回中介绍的是两个嵌套的Fragment之间的交互。与之前介绍的Fragment相比,它们还在同一个Activity中,只是它们之间多了一层嵌套的关系。不像之前介绍的Fragment一样,它们虽然在同一个Activity中,但是相互之间没有任何关系。

两个嵌套Fragment之间的交互相对方便一些,因为它们之间多一层嵌套关系。为了方便说明,我们假设有两个FragmentA和B,并且A是父Fragment,B嵌套在A中。如果A想和B进行交互的话,那么A可以借助FragmentManager的方法获取到B,然后就可以和B进行交互了。如果B想和A进行交互,那么可以借助它们所在的Activity来完成交互,这个我们在前面的章回中介绍过,因此就不再详细说明了。接下来我们将结合代码来演示A如何与B进行交互,这便是本章回的主要内容。

  • 1.创建两个Fragment,它们分别是FragmentA和FragmentB。如何创建,我们在前面章回中介绍过,这里不做详细说明。
  • 2.在FragmentA中获取FragmentB的对象,然后通过FragmentB的对象来实现它们之间的交互,具体的代码如下所示:
FragmentManager fm =  getChildFragmentManager();           //首先获取FragmentManager
FragmentB mFragmentB = (FragmentB)fm.findFragmentById(R.id.fragmentB); //然后通过FragmentManager找到FragmentB对象

if(mFragmentB != null)
    mFragmentB.func(); //使用FragmentB中的方法,可以看作是FragmentA与FragmentB之间的交互

看官们,这便是嵌套在一起的两个Fragment之间的交互方法,与没有嵌套关系的Fragment相比,它们在获取FragmentManager的方法上不一样,一个使用的是FragmentgetchildFragmentManager()方法,而另外一个使用的是ActivitygetSupportFragmentManager()方法。类不同其方法自然也不同,这个就不多说了。除了这个不同点之外,其它的交互方式完全一致,大家可以进行对比,这样也方便掌握新知识。

各位看官,关于Android中Fragment的例子咱们就介绍到这里,欲知后面还有什么例子,且听下回分解!


作者:talk_8 发表于2017/11/26 21:39:14 原文链接
阅读:22 评论:0 查看评论

Hadoop-2.7.3源码分析:MapReduce作业提交源码跟踪

$
0
0

1、提交Job

MapReduce程序框架请参考
http://blog.csdn.net/chengyuqiang/article/details/72804007

@Override
    public int run(String[] args) throws Exception {
        //读取配置文件
        Configuration conf = getConf(); 
        //设置参数
        conf.set("fs.defaultFS", "hdfs://192.168.11.81:9000");
        //自定义key value 之间的分隔符(默认为tab)
        conf.set("mapreduce.input.keyvaluelinerecordreader.key.value.separator", ",");
        // Job表示一个MapReduce任务,构造器第二个参数为Job的名称。
        Job job = Job.getInstance(conf, "MapReduceTemplate");
        job.setJarByClass(MapReduceTemplate.class);//主类
        Path in = new Path(args[0]);//输入路径
        Path out = new Path(args[1]);//输出路径
        FileSystem hdfs = out.getFileSystem(conf);
        if (hdfs.isDirectory(out)) {//如果输出路径存在就删除
            hdfs.delete(out, true);
        }
        FileInputFormat.setInputPaths(job, in);//文件输入
        FileOutputFormat.setOutputPath(job, out);//文件输出
        job.setMapperClass(MapTemplate.class); //设置自定义Mapper
        job.setReducerClass(ReduceTemplate.class); //设置自定义Reducer
        job.setInputFormatClass(KeyValueTextInputFormat.class);//文件输入格式
        job.setOutputFormatClass(TextOutputFormat.class);//文件输出格式
        job.setOutputKeyClass(Text.class);//设置作业输出值 Key 的类 
        job.setOutputValueClass(Text.class);//设置作业输出值 Value 的类 
        return job.waitForCompletion(true)?0:1;//等待作业完成退出
    } 

2、进入Job.waitForCompletion()方法

在判断状态state可以提交Job后,执行submit()方法。monitorAndPrintJob()方法会不断的刷新获取job运行的进度信息,并打印。boolean参数verbose为true表明要打印运行进度,为false就只是等待job运行结束,不打印运行日志。

 /**
   * Submit the job to the cluster and wait for it to finish.
   * @param verbose print the progress to the user
   * @return true if the job succeeded
   * @throws IOException thrown if the communication with the 
   *         <code>JobTracker</code> is lost
   */
  public boolean waitForCompletion(boolean verbose
                                   ) throws IOException, InterruptedException,
                                            ClassNotFoundException {
    //当state为define时,则提交
    if (state == JobState.DEFINE) {
      submit(); //提交过程在submit()方法中
    }
    //verbose是waitForCompletion(verbose)传进来的true,表示执行monitorAndPrintJob()
    //检测并打印Job相关信息
    if (verbose) {
      monitorAndPrintJob();
    } else {
      // get the completion poll interval from the client.
      //从客户端获得完成轮询时间间隔
      int completionPollIntervalMillis = 
        Job.getCompletionPollInterval(cluster.getConf());
      while (!isComplete()) {
        try {
          Thread.sleep(completionPollIntervalMillis);
        } catch (InterruptedException ie) {
        }
      }
    }
    //返回一个boolean值,表示作业是否成功提交
    return isSuccessful();
  }

3、进入submit()方法

submit方法首先是确保当前的Job的状态是处于DEFINE,否则不能提交Job。然后启用新的API,即org.apache.hadoop.mapreduce下的Mapper和Reducer。Connect()方法会产生一个Client实例,用来和ResourceManager通信。其实submit()方法里关键的两处代码,一处是调用connect()方法,另一处是获取一个JobSubmitter类的实例,调用该对象的submitJobInternal方法来提交任务。

  /**
   * Submit the job to the cluster and return immediately.
   * @throws IOException
   */
  public void submit() 
         throws IOException, InterruptedException, ClassNotFoundException {
    //再次检查作业的状态
    ensureState(JobState.DEFINE);
    //两套API,这里使用新API
    setUseNewAPI();
    connect();
    //初始化工作,为cluster赋值,Client即是提交器,分为本体提交器和Yarn提交器,由配置文件决定
    final JobSubmitter submitter = 
        getJobSubmitter(cluster.getFileSystem(), cluster.getClient());
    status = ugi.doAs(new PrivilegedExceptionAction<JobStatus>() {
      public JobStatus run() throws IOException, InterruptedException, 
      ClassNotFoundException {
        return submitter.submitJobInternal(Job.this, cluster);//提交
      }
    });
    state = JobState.RUNNING;
    LOG.info("The url to track the job: " + getTrackingURL());
   }

4、首先看connect()方法

MapReduce作业提交时连接集群是通过Job类的connect()方法实现的,它实际上是构造集群Cluster实例cluster

   private synchronized void connect()
          throws IOException, InterruptedException, ClassNotFoundException {
    if (cluster == null) {//若cluster空,则构造Cluster实例
      //cluster是连接MapReduce集群的工具,提供了远程获取MapReduce集群的方法
      cluster = 
        ugi.doAs(new PrivilegedExceptionAction<Cluster>() {
                   public Cluster run()
                          throws IOException, InterruptedException, 
                                 ClassNotFoundException {
                     return new Cluster(getConfiguration());
                   }
                 });
    }
  }

5、进入return的Cluster(getConfiguration())构造方法

来到了Cluster类。先来看下Cluster类的成员信息。

package org.apache.hadoop.mapreduce;

import ...
/**
 * Provides a way to access information about the map/reduce cluster.
 */
@InterfaceAudience.Public
@InterfaceStability.Evolving
public class Cluster {

  @InterfaceStability.Evolving
  public static enum JobTrackerStatus {INITIALIZING, RUNNING};
  private ClientProtocolProvider clientProtocolProvider;  //客户端通信协议提供者
  private ClientProtocol client;        //客户端通信协议实例
  private UserGroupInformation ugi;     //用户组信息
  private Configuration conf;           //配置信息
  private FileSystem fs = null;         //文件系统实例
  private Path sysDir = null;           //系统路径
  private Path stagingAreaDir = null;   //作业资源存放路径
  private Path jobHistoryDir = null;    //作业历史路径
  private static final Log LOG = LogFactory.getLog(Cluster.class);  //日志
  //客户端通信协议提供者加载器
  private static ServiceLoader<ClientProtocolProvider> frameworkLoader =
      ServiceLoader.load(ClientProtocolProvider.class);

  static {
    ConfigUtil.loadResources();
  }

  public Cluster(Configuration conf) throws IOException {
    this(null, conf);
  }

  public Cluster(InetSocketAddress jobTrackAddr, Configuration conf) 
      throws IOException {
    this.conf = conf;  //设置配置信息
    this.ugi = UserGroupInformation.getCurrentUser(); //获取当前用户
    initialize(jobTrackAddr, conf);  //完成初始化
  }

  ...
}

Cluster最重要的两个成员变量是客户端通信协议提供者ClientProtocolProvider实例clientProtocolProvider和客户端通信协议ClientProtocol实例client,而后者是依托前者的create()方法生成的。 Cluster类提供了两个构造函数。

6、进入initialize()方法

  private void initialize(InetSocketAddress jobTrackAddr, Configuration conf)
      throws IOException {

    synchronized (frameworkLoader) {
      //依次取出每个ClientProtocolProvider,通过其create()方法构造ClientProtocol实例
      for (ClientProtocolProvider provider : frameworkLoader) {
        LOG.debug("Trying ClientProtocolProvider : " + provider.getClass().getName());
        ClientProtocol clientProtocol = null; 
        try {
          //如果配置文件没有配置YARN信息,则构建LocalRunner,MR任务本地运行
          //如果配置文件有配置YARN信息,则构建YarnRunner,MR任务在YARN集群上运行
          if (jobTrackAddr == null) {
            clientProtocol = provider.create(conf);
          } else {
            clientProtocol = provider.create(jobTrackAddr, conf);
          }
          //设置成员变量clientProtocolProvider和client,并退出循环
          if (clientProtocol != null) {
            clientProtocolProvider = provider;
            client = clientProtocol;
            LOG.debug("Picked " + provider.getClass().getName()
                + " as the ClientProtocolProvider");
            break;
          }else {
            LOG.debug("Cannot pick " + provider.getClass().getName()
                + " as the ClientProtocolProvider - returned null protocol");
          }
        }catch (Exception e) {
          LOG.info("Failed to use " + provider.getClass().getName() + " due to error: ", e);
        }
      }
    }
    //如果clientProtocolProvider或client空,抛出IOException
    if (null == clientProtocolProvider || null == client) {
      throw new IOException(
          "Cannot initialize Cluster. Please check your configuration for "
              + MRConfig.FRAMEWORK_NAME
              + " and the correspond server addresses.");
    }
  }

7、ClientProtocolProvider实现类LocalClientProtocolProvider

上面create()方法时提到了两种ClientProtocolProvider实现类。
MapReduce中,ClientProtocolProvider抽象类的实现共有YarnClientProtocolProvider、LocalClientProtocolProvider两种,前者为Yarn模式,而后者为Local模式。
这里写图片描述

我们先看下看下Local模式,LocalClientProtocolProvider的create()方法,代码如下

package org.apache.hadoop.mapred;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.mapreduce.MRConfig;
import org.apache.hadoop.mapreduce.protocol.ClientProtocol;
import org.apache.hadoop.mapreduce.protocol.ClientProtocolProvider;

@InterfaceAudience.Private
public class LocalClientProtocolProvider extends ClientProtocolProvider {

  @Override
  public ClientProtocol create(Configuration conf) throws IOException {
    //两个常量:"mapreduce.framework.name","local"
    String framework =
        conf.get(MRConfig.FRAMEWORK_NAME, MRConfig.LOCAL_FRAMEWORK_NAME);
    //若framework是local,则返回LocalJobRunner,并且设置Map任务数1;否则返回null
    if (!MRConfig.LOCAL_FRAMEWORK_NAME.equals(framework)) {
      return null;
    }
    conf.setInt(JobContext.NUM_MAPS, 1);
    return new LocalJobRunner(conf);
  }

  @Override
  public ClientProtocol create(InetSocketAddress addr, Configuration conf) {
    return null; // LocalJobRunner doesn't use a socket
  }

  @Override
  public void close(ClientProtocol clientProtocol) {
    // no clean up required
  }

}

由上可知,MapReduce需要看参数mapreduce.framework.name确定连接模式,但默认是Local模式的。

8、ClientProtocolProvider实现类YarnClientProtocolProvider

再来看Yarn模式,看下YarnClientProtocolProvider的create()方法

package org.apache.hadoop.mapred;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.mapreduce.MRConfig;
import org.apache.hadoop.mapreduce.protocol.ClientProtocol;
import org.apache.hadoop.mapreduce.protocol.ClientProtocolProvider;
public class YarnClientProtocolProvider extends ClientProtocolProvider {

  @Override
  public ClientProtocol create(Configuration conf) throws IOException {
    //若参数mapreduce.framework.name配置为Yarn,则构造一个YARNRunner实例并返回,否则返回null
    if (MRConfig.YARN_FRAMEWORK_NAME.equals(conf.get(MRConfig.FRAMEWORK_NAME))) {
      return new YARNRunner(conf);
    }
    return null;
  }

  @Override
  public ClientProtocol create(InetSocketAddress addr, Configuration conf)
      throws IOException {
    return create(conf);
  }

  @Override
  public void close(ClientProtocol clientProtocol) throws IOException {
    if (clientProtocol instanceof YARNRunner) {
      ((YARNRunner)clientProtocol).close();
    }
  }
}

到了这里,我们就能够知道一个很重要的信息,Cluster中客户端通信协议ClientProtocol实例,要么是Yarn模式下的YARNRunner,要么就是Local模式下的LocalJobRunner。

9、YARNRunner

以Yarn模式来分析MapReduce集群连接,看下YARNRunner的实现。
最重要的一个变量就是ResourceManager的代理ResourceMgrDelegate类型的resMgrDelegate实例,Yarn模式下整个MapReduce客户端就是由它负责与Yarn集群进行通信,完成诸如作业提交、作业状态查询等过程,通过它获取集群的信息,其内部有一个YarnClient实例YarnClient,负责与Yarn进行通信,还有ApplicationId、ApplicationSubmissionContext等与特定应用程序相关的成员变量。以后有时间还要详细介绍这个对象。另外一个比较重要的变量就是客户端缓存ClientCache实例clientCache。

package org.apache.hadoop.mapred;

import ...

/**
 * This class enables the current JobClient (0.22 hadoop) to run on YARN.
 */
@SuppressWarnings("unchecked")
public class YARNRunner implements ClientProtocol {

  private static final Log LOG = LogFactory.getLog(YARNRunner.class);
  //记录工厂RecordFactory实例
  private final RecordFactory recordFactory = RecordFactoryProvider.getRecordFactory(null);
  private ResourceMgrDelegate resMgrDelegate;   //ResourceManager代理实例对象
  private ClientCache clientCache;              //客户端缓存实例
  private Configuration conf;                   //配置信息
  private final FileContext defaultFileContext; //文件上下文实例

  /**
   * Yarn runner incapsulates the client interface of
   * yarn
   * @param conf the configuration object for the client
   */
  //先构造ResourceManager代理ResourceMgrDelegate实例,再调用两个参数的YARNRunner构造器
  public YARNRunner(Configuration conf) {
   this(conf, new ResourceMgrDelegate(new YarnConfiguration(conf)));
  }

  /**
   * Similar to {@link #YARNRunner(Configuration)} but allowing injecting
   * {@link ResourceMgrDelegate}. Enables mocking and testing.
   * @param conf the configuration object for the client
   * @param resMgrDelegate the resourcemanager client handle.
   */
  //先构造客户端缓存ClientCache实例,再调用三个参数的YARNRunner构造器
  public YARNRunner(Configuration conf, ResourceMgrDelegate resMgrDelegate) {
   this(conf, resMgrDelegate, new ClientCache(conf, resMgrDelegate));
  }

  /**
   * Similar to {@link YARNRunner#YARNRunner(Configuration, ResourceMgrDelegate)}
   * but allowing injecting {@link ClientCache}. Enable mocking and testing.
   * @param conf the configuration object
   * @param resMgrDelegate the resource manager delegate
   * @param clientCache the client cache object.
   */
  public YARNRunner(Configuration conf, ResourceMgrDelegate resMgrDelegate,
      ClientCache clientCache) {
    this.conf = conf;  //成员变量赋值
    try {
      this.resMgrDelegate = resMgrDelegate;
      this.clientCache = clientCache;
      //获取文件上下文defaultFileContext实例
      this.defaultFileContext = FileContext.getFileContext(this.conf);
    } catch (UnsupportedFileSystemException ufe) {
      throw new RuntimeException("Error in instantiating YarnClient", ufe);
    }
  }

  ...
}

YARNRunner一共提供了三个构造函数,而我们之前说的WordCount作业提交时,其内部调用的是YARNRunner带有一个参数的构造函数,它会先构造ResourceManager代理ResourceMgrDelegate实例,然后再调用两个参数的构造函数,继而构造客户端缓存ClientCache实例,然后再调用三个参数的构造函数,而最终的构造函数只是进行简单的类成员变量赋值,然后通过FileContext的静态getFileContext()方法获取文件山下文FileContext实例defaultFileContext。

10、connect()方法总结

MapReduce作业提交时连接集群是通过Job的connect()方法实现的,它实际上是构造集群Cluster实例cluster。Cluster为连接MapReduce集群的一种工具,提供了一种获取MapReduce集群信息的方法。在Cluster内部,有一个与集群进行通信的客户端通信协议ClientProtocol实例client,它由ClientProtocolProvider的静态create()方法构造,而Hadoop2.x中提供了两种模式的ClientProtocol,分别为Yarn模式的YARNRunner和Local模式的LocalJobRunner,Cluster实际上是由它们负责与集群进行通信的,而Yarn模式下,ClientProtocol实例YARNRunner对象内部有一个ResourceManager代理ResourceMgrDelegate实例resMgrDelegate,Yarn模式下整个MapReduce客户端就是由它负责与Yarn集群进行通信,完成诸如作业提交、作业状态查询等过程,通过它获取集群的信息。

11、submitJobInternal()方法

再次回到(3、进入submit()方法)submit()方法,上面已经介绍了connect()方法,下面开始介绍另一个重要的的方法submitJobInternal()。

该方法隶属于JobSubmitter类,顾名思义,该类是MapReduce中作业提交者,而实际上JobSubmitter除了构造方法外,对外提供的唯一一个非private成员变量或方法就是submitJobInternal()方法,它是提交Job的内部方法,实现了提交Job的所有业务逻辑。

作者:chengyuqiang 发表于2017/11/26 21:50:55 原文链接
阅读:5 评论:0 查看评论

BZOJ2330(SCOI2011)[糖果]--差分约束系统

$
0
0

【链接】
bzoj2330

【解题报告】

差分约束系统裸题。不会可以去看百科。

Ps:注意加一个点会T。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=100005,maxm=300005;
int n,m,tot,dst[maxn],num[maxn],que[maxn],lnk[maxn],son[maxm],nxt[maxm];
bool vis[maxn],w[maxm];
LL ans;
inline char nc()
{
    static char buf[100000],*l,*r;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    if (l==r) return EOF; return *l++;
}
inline int Read()
{
    int res=0; char ch=nc();
    while (ch<'0'||ch>'9') ch=nc();
    while (ch>='0'&&ch<='9') res=res*10+ch-48,ch=nc();
    return res;
}
void Add(int x,int y,bool z) {w[++tot]=z; son[tot]=y; nxt[tot]=lnk[x]; lnk[x]=tot;}
bool Spfa()
{
    memset(num,0,sizeof(num));
    int hed=0,til=0;
    for (int i=1; i<=n; i++) que[til=(til+1)%maxn]=i,vis[i]=1,dst[i]=1;
    while (hed!=til)
    {
        int x=que[hed=(hed+1)%maxn]; vis[x]=0;
        for (int j=lnk[x]; j; j=nxt[j])
         if (dst[x]+w[j]>dst[son[j]])
          {
            if (++num[son[j]]>=n) return 0;
            dst[son[j]]=dst[x]+w[j];
            if (!vis[son[j]])
             {
                que[til=(til+1)%maxn]=son[j]; vis[son[j]]=1;
                if (dst[que[til]]>dst[que[(hed+1)%maxn]]) swap(que[til],que[(hed+1)%maxn]);
             }
          }
    }
    return 1;
}
int main()
{
    freopen("2330.in","r",stdin);
    freopen("2330.out","w",stdout);
    n=Read(); m=Read(); tot=0;
    memset(lnk,0,sizeof(lnk));
    for (int i=1; i<=m; i++)
    {
        int x=Read(),a=Read(),b=Read();
        switch (x)
        {
            case 1:Add(a,b,0);Add(b,a,0);break;
            case 2:if (a==b) {printf("-1"); return 0;}
                   Add(a,b,1);break;
            case 3:Add(b,a,0);break;
            case 4:if (a==b) {printf("-1"); return 0;}
                   Add(b,a,1);break;
            case 5:Add(a,b,0);break;
        }
    }
    if (!Spfa()) {printf("-1"); return 0;}
    ans=0; for (int i=1; i<=n; i++) ans+=dst[i];
    printf("%lld\n",ans);
    return 0;
}
作者:CHNWJD 发表于2017/11/26 17:50:07 原文链接
阅读:135 评论:0 查看评论

linux vim 编辑器之多文件多窗口编辑

$
0
0

有时可能需要在多个文件之间来回操作,但是关闭一个文件再打开另外一个文件这样来回操作未免显得太笨拙了。还好linux提供了多文件多窗口的模式。
同时打开多个文件

vim filename1 filename2 filename3 ....

多文件编辑按键

:files  查看当前打开了哪些文件
:n  切换到下一个文件
:N  切换到上一个文件

同时打开多个文件之后,就可以在file1中复制数据再粘贴到file2中
,操作起来不要太爽。但是有人会说我想操作几个文件的同时,想能同时看到几个文件,而不是每次都要切换换个窗口。这个linux可以加个-o 参数来实现

vim  -o filename1 filename2 ...  水平分割窗口
vim  -O  filename1 filename2 ... 垂直分割窗口

vim -O test.py testMysql.py 垂直分割的方式同时打开两个文件test.py testMysql.py 效果如下图所示,两个窗口之间可以使用Ctrl+w+←或者Ctrl+w+→来左右切换。

这里写图片描述

vim -o test.py testMysql.py 水平分割窗口打开两个文件,效果如下图,可以使用Ctrl+w+↑或者Ctrl+w+↓来上下切换两个窗口。

这里写图片描述

有时想对同一个文件进行窗口分割,这样方便对比。除了可以使用vim -o test.py test.py 这种方式分割外,还可以这样操作

先打开文件
vim test.py
再输入指令
:sp

这样就能以上下窗口的方式打开这个文件,效果如下图所示,同样可以使用Ctrl+w+↑或者Ctrl+w+↓来上下切换窗口

这里写图片描述

作者:u012062455 发表于2017/11/26 22:10:09 原文链接
阅读:45 评论:0 查看评论

linux vim编辑器之环境设置

$
0
0

vim有如下环境参数
:set nu
:set nonu
就是设置与取消行号

:set hlsearch
:set nohlsearch
hlsearch就是high light search(高亮度查找)。这个就是设置是否将查找的字符串反白的设置值。默认是hlsearch

:set autoindent
:set noautoindent
表示是否自动缩排,autoindent就是自动缩排

:set backup
表示是否自动保存备份文件,一般是nobackup的,如果设置backup的话,那么当你改动任何一个文件是
,则原文件会在源文件同一目录下被另存为一个文件名为filename~的文件。

:set ruler 设置显示右下角的状态栏说明

:set showmode 设置显示左下角的状态栏说明

:set backspace=(012)
在我们按下i进入编辑模式后,可以利用刻个件(backspace)来删除任意字符的
。但是,某些distribution则不是如此。此时,我们就可以通过设置backspace来设置。
当backspace为2时,就是可以删除任意字符;为0或1时,仅可删除刚才输入的字符,而无法删除原本就已经存在的文字了

:set all 显示目前所有的环境参数设置值

:set 显示与系统默认不同的设置参数,一般来说就是你有自行变动过的设置参数

:syntax on
:syntax off
表示是否依据程序相关语法显示不同颜色。

:set bg=dark
:set bg=light
可用以显示不同的颜色色调默认是light。如果你经常发现批注的字体深蓝色实在很不容易看,
那么这里可以设置为dark,会有不同的样式

每次使用vim打开文件的时候,都进行设置很麻烦,假设我现在想使用vim打开文件的时候,文件自动显示行号,添加新行时自动缩排,背景颜色为dark,那么可以这样设置。

新建一个文件
touch ~/.vimrc
在文件中做如下设置
set autoindent
set nu
set bg=dark
syntax on

随便打开一个文件,就会自动显示行号,背景色也和之前不一样了

这里写图片描述

作者:u012062455 发表于2017/11/26 22:36:33 原文链接
阅读:50 评论:0 查看评论

poj2970The lazy programmer 优先队列+贪心

$
0
0
The lazy programmer
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 2421   Accepted: 605

Description

A new web-design studio, called SMART (Simply Masters of ART), employs two people. The first one is a web-designer and an executive director at the same time. The second one is a programmer. The director is so a nimble guy that the studio has already got N contracts for web site development. Each contract has a deadline di.

It is known that the programmer is lazy. Usually he does not work as fast as he could. Therefore, under normal conditions the programmer needs bi of time to perform the contract number i. Fortunately, the guy is very greedy for money. If the director pays him xi dollars extra, he needs only (bi − ai xi) of time to do his job. But this extra payment does not influent other contract. It means that each contract should be paid separately to be done faster. The programmer is so greedy that he can do his job almost instantly if the extra payment is (bi ⁄ ai) dollars for the contract number i.

The director has a difficult problem to solve. He needs to organize programmer’s job and, may be, assign extra payments for some of the contracts so that all contracts are performed in time. Obviously he wishes to minimize the sum of extra payments. Help the director!

Input

The first line of the input contains the number of contracts N (1 ≤ N ≤ 100 000, integer). Each of the next N lines describes one contract and contains integer numbers aibidi (1 ≤ aibi ≤ 10 000; 1 ≤ di ≤ 1 000 000 000) separated by spaces.

Output

The output needs to contain a single real number S in the only line of file. S is the minimum sum of money which the director needs to pay extra so that the programmer could perform all contracts in time. The number must have two digits after the decimal point.

Sample Input

2
20 50 100
10 100 50

Sample Output

5.00

题意:给出每个任务的deadline和所需时间,以及每个时间段单位money可以买的时间。求需要花的最少money。

思路:依照时间以此解决每个任务,时间不够时从前面的任务中缩减(购买)时间。

用变量sum维护完成当前任务所需的时间。
如果sum超过deadline,从之前的任务中取出一个买时间,直到sum<=deadline.
买到的时间=a*x,a越大越划算。因此用优先队列维护可以买时间的任务。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
int n;
struct node{
	int a,b,d;
	bool operator < (const node&x)const{//优先队列排序
		return a < x.a;
	}
}con[100001];

bool cmp(const node &a,const node &b)//数组排序
{
	return a.d<b.d;
}
priority_queue<node> qu;

int main()
{
	scanf("%d",&n);
	for (int i = 0; i < n; ++i) 
		scanf("%d%d%d",&con[i].a,&con[i].b,&con[i].d);
	sort(con,con+n,cmp);
	int sum = 0;	//维护完成当前任务所需时间
	double ans = 0.0;//完成所有任务所需要的最小费用
	for (int i = 0; i < n; ++i){
		sum +=  con[i].b;
		qu.push(con[i]);//当前任务也可以购买时间
		while(sum>con[i].d) {
		    node x = qu.top();qu.pop();
		    if(x.b>(sum-con[i].d)){
		    	x.b -= sum-con[i].d;
		    	ans += (sum-con[i].d)*1.0/x.a;
		    	sum = con[i].d;
		    	qu.push(x);
		    }else{
		    	ans += x.b*1.0/x.a;
		    	sum -= x.b;
		    }
		}
	}
	printf("%.2f\n",ans);
	return 0;
}


作者:xxiaobaib 发表于2017/11/26 22:42:29 原文链接
阅读:60 评论:0 查看评论

【python数据挖掘课程】十八.线性回归及多项式回归分析四个案例分享

$
0
0
这是《Python数据挖掘课程》系列文章,也是我这学期大数据金融学院上课的部分内容。本文主要讲述和分享线性回归作业中,学生们做得比较好的四个案例,经过我修改后供大家学习,内容包括:
    1.线性回归预测Pizza价格案例
    2.线性回归分析波士顿房价案例
    3.随机数据集一元线性回归分析和三维回归分析案例
    4.Pizza数据集一元线性回归和多元线性回归分析

本篇文章为初始篇,基础文章希望对你有所帮助,如果文章中存在错误或不足支持,还请海涵~自己真的太忙了,只能挤午休或深夜的时间学习新知识,但也得加油。


前文参考:
【Python数据挖掘课程】一.安装Python及爬虫入门介绍
【Python数据挖掘课程】二.Kmeans聚类数据分析及Anaconda介绍
【Python数据挖掘课程】三.Kmeans聚类代码实现、作业及优化
【Python数据挖掘课程】四.决策树DTC数据分析及鸢尾数据集分析
【Python数据挖掘课程】五.线性回归知识及预测糖尿病实例
【Python数据挖掘课程】六.Numpy、Pandas和Matplotlib包基础知识
【Python数据挖掘课程】七.PCA降维操作及subplot子图绘制
【Python数据挖掘课程】八.关联规则挖掘及Apriori实现购物推荐
【Python数据挖掘课程】九.回归模型LinearRegression简单分析氧化物数据
【python数据挖掘课程】十.Pandas、Matplotlib、PCA绘图实用代码补充
【python数据挖掘课程】十一.Pandas、Matplotlib结合SQL语句可视化分析
【python数据挖掘课程】十二.Pandas、Matplotlib结合SQL语句对比图分析
【python数据挖掘课程】十三.WordCloud词云配置过程及词频分析
【python数据挖掘课程】十四.Scipy调用curve_fit实现曲线拟合
【python数据挖掘课程】十五.Matplotlib调用imshow()函数绘制热图
【python数据挖掘课程】十六.逻辑回归LogisticRegression分析鸢尾花数据
【python数据挖掘课程】十七.社交网络Networkx库分析人物关系(初识篇)



一. 线性回归预测Pizza价格案例


1.数据集介绍

本章主要使用线性回归预测Pizza的价格,由于直径大小不同的Pizza,其价格也是不同的。这是一个非常经典的案例,主要包括两个特征——Pizza直径(单位:英寸)和Pizza价格(单位:美元)。假设读者现在去到一家西餐厅,看到Pizza的菜单,现在需要通过机器学习的方法构造一个一元线性回归模型,通过分析匹萨的直径与价格的数据的线性关系,来预测任意直径匹萨的价格。 数据集共十行,包括两个特征,如下表10.1所示。


2.线性回归分析

线性回归基础步骤主要包括:
    1.导入数据集,采用列表的形式定义直接和价格两列数据。
    2.调用Scikit-learn机器学习包中线性回归模型。
    3.调用fit()函数对直径和价格进行训练。
    4.调用predice()函数对数据集进行预测。
    5.对线性回归算法进行评价。
    6.可视化分析并绘制相关图形,直观的呈现算法模型的结果。
线性回归分析的完整代码如下:

# -*- coding: utf-8 -*-
from sklearn.linear_model import LinearRegression

#数据集 直径、价格
x = [[5],[6],[7],[8],[10],[11],[13],[14],[16],[18]]
y = [[6],[7.5],[8.6],[9],[12],[13.6],[15.8],[18.5],[19.2],[20]]
print x
print y

clf = LinearRegression()
clf.fit(x,y)
pre = clf.predict([12])[0]
print(u'预测直径为12英寸的价格: $%.2f' % pre)

通过调用sklearn机器学习包中linear_model子类的LinearRegression线性回归模型,然后fit()函数用来分析模型参数,predict()通过fit()算出模型参数构成的模型,对解释变量进行预测获得其结果。上面的代码输出如下所示:

[[5], [6], [7], [8], [10], [11], [13], [14], [16], [18]]
[[6], [7.5], [8.6], [9], [12], [13.6], [15.8], [18.5], [19.2], [20]]
预测直径为12英寸的价格: $14.42

可以发现直径为12英寸的Pizza价格为14.42美元。同时它生成了一个一元线性回归模型,即:y = a*x + b。其中,y表示响应变量的预测值,这个示例为Pizza的价格预测值;x为因变量,表示Pizza的直径。


3.可视化分析

接下来需要对数据集进行可视化分析,首先需要调用Matplotlib扩展包绘制直径和价格的散点图,代码如下:

# -*- coding: utf-8 -*-
from sklearn.linear_model import LinearRegression

#数据集 直径、价格
x = [[5],[6],[7],[8],[10],[11],[13],[14],[16],[18]]
y = [[6],[7.5],[8.6],[9],[12],[13.6],[15.8],[18.5],[19.2],[20]]
print x
print y

clf = LinearRegression()
clf.fit(x,y)
pre = clf.predict([12])[0]
print(u'预测直径为12英寸的价格: $%.2f' % pre)
x2 = [[0],[12],[15],[25]]
y2 = clf.predict(x2)

import matplotlib.pyplot as plt
plt.figure()
plt.rcParams['font.sans-serif'] = ['SimHei'] #指定默认字体
plt.title(u"线性回归预测Pizza直径和价格")
plt.xlabel(u"x")
plt.ylabel(u"price")
plt.axis([0,25,0,25])
plt.scatter(x,y,marker="s",s=20)
plt.plot(x2,y2,"g-")
plt.show()

输出图形如下所示,其中(x2,y2)是训练后的回归模型进行预测的结果,为一条直线。





二. 线性回归分析波士顿房价案例


1.数据集

波士顿房价数据集(Boston House Price Dataset)包含对房价的预测(以千美元计数),给定的条件是房屋及其相邻房屋的详细信息。该数据集涉及一个回归问题,通过进行线性回归分析可以预测波斯顿房价数据。而且由于Sklearn机器学习包中已经自带了该数据集,故直接引用该数据集,获取其中某两列数据,对其进行分析预测。

该数据集的下载地址为:http://lib.stat.cmu.edu/datasets/boston,也可以从UCI机器学习知识库中下载,每个类的观察值数量是均等的,共有 506 行数据,13 个输入变量和1个输出变量,数据集如下图11.1所示,这些数据从1978年开始统计,涵盖了波士顿不同郊区房屋14中特征信息。



在做数据分析过程中,通常需要将数据集划分为训练集和预测集,这里作者将前406行作为训练集,最后100行作为预测集,划分代码如下:

# -*- coding: utf-8 -*-
#导入数据集boston
from sklearn.datasets import load_boston
import numpy as np 
boston = load_boston()    
print boston.data.shape, boston.target.shape
print boston.data[0]
print boston.target

#划分数据集
boston_temp = boston.data[:, np.newaxis, 5]   
x_train = boston_temp[:-100]      #训练样本  
x_test = boston_temp[-100:]       #测试样本 后100行  
y_train = boston.target[:-100]    #训练标记  
y_test = boston.target[-100:]     #预测对比标记

2.线性回归分析

线性回归过程主要如下:
    1.导入数据集,波士顿房价数据。
    2.划分数据集为训练集和测试集,采用406和100的比例。
    3.导入线性回归模型LinearRegression。
    4.对训练集进行训练操作,同时预测数据集结果。
    5.可视化画图分析及结果评估。

线性回归分析波士顿房价数据集的代码如下:

# -*- coding: utf-8 -*-
from sklearn.datasets import load_boston
import numpy as np 
boston = load_boston()    
print boston.data.shape, boston.target.shape

#划分数据集
boston_temp = boston.data[:, np.newaxis, 5]   
x_train = boston_temp[:-100]      #训练样本  
x_test = boston_temp[-100:]       #测试样本 后100行  
y_train = boston.target[:-100]    #训练标记  
y_test = boston.target[-100:]     #预测对比标记

#回归分析
from sklearn.linear_model import LinearRegression 
clf = LinearRegression()  
clf.fit(x_train, y_train)  

#算法评估
pre = clf.predict(x_test)
print u"预测结果", pre
print u"真实结果", y_test
cost = np.mean(y_test-pre)**2  
print u'平方和计算:', cost  
print u'系数', clf.coef_   
print u'截距', clf.intercept_    
print u'方差', clf.score(x_test, y_test) 

#绘图分析
import matplotlib.pyplot  as plt
plt.title(u'LinearRegression Boston')     
plt.xlabel(u'x')                   
plt.ylabel(u'price')          
plt.scatter(x_test, y_test, color = 'black')  
plt.plot(x_test, clf.predict(x_test), color='blue', linewidth = 3)
for idx, m in enumerate(x_test):  
    plt.plot([m, m],[y_test[idx],pre[idx]], 'r-')    
plt.show()   

对该算法进行评估,线性回归算法可以计算线性方程的系数和截距,即coef_为系数、intercept_为截距。同时可以通过clf.score(x_test,y_test)计算其方差。

平方和计算: 32.6621132918
系数 [ 9.52462596]
截距 -36.1965235122
方差 -1.83449598504  
输出如下图所示:





三. 随机数据集线性回归分析和三维回归分析案例

1.随机数据集

本章将生成一个随机数据集供您使用,通过该数据集的线性回归分析,您也能了解到相关应用知识。同时,将进一步深入讲解线性回归拟合方程的知识,希望本章对您有所帮助。

随机数生成主要调用Numpy扩展包中的random函数或arange,调用函数arange(0,50,0.2)实现,随机生成0到50个数据,其间隔为0.2。得到X数据集之后,作者随机定义一个函数绘制对应的Y坐标,再调用Matplotlib扩展包可以对数据集进行可视化分析,并绘制相关的散点图。核心代码如下:

import numpy as np
import math
X =  np.arange(0,50,0.2) 
print X
xArr = []
yArr = []
for n in X:
    xArr.append(n)
    y = 0.7*n + np.random.uniform(0,1)*math.sin(n)*2 - 3
    yArr.append(y)

import matplotlib.pyplot as plt
plt.plot(X, yArr, 'go')
plt.show()
输出如下图所示:


接下来需要调用Sklearn机器学习扩展包相关函数进行线性回归分析。


2.线性回归

完整代码如下:

# -*- coding: utf-8 -*-
import numpy as np
import math

#随机数生成
X =  np.arange(0,50,0.2) 
print X
xArr = []
yArr = []
for n in X:
    xArr.append(n)
    y = 0.7*n + np.random.uniform(0,1)*math.sin(n)*2 - 3
    yArr.append(y)

#线性回归分析
from sklearn.linear_model import LinearRegression
clf = LinearRegression()
print clf
X =  np.array(X).reshape((len(X),1))     #list转化为数组
yArr = np.array(yArr).reshape((len(X),1))
clf.fit(X,yArr)
pre = clf.predict(X)

import matplotlib.pyplot as plt
plt.plot(X, yArr, 'go')
plt.plot(X, pre, 'r', linewidth=3)
plt.show()
输出如下所示:



同时补充一段3D绘制的代码,随机坐标生成后,需要调用mpl_toolkits.mplot3d子类中Axes3D类生成对应的3D图形。使用线性回归对其进行分析过程中,不同于二维可视化分析,三维需要将xx和yy标定成输入变量,zz为输出变量进行训练,再预测其结果。完整代码如下所示:
# -*- coding: utf-8 -*-
import numpy as np
from sklearn import linear_model
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import math

#linspace:开始值、终值和元素个数创建表示等差数列的一维数组
xx, yy = np.meshgrid(np.linspace(0,10,20), np.linspace(0,100,20))
zz = 2.4 * xx + 4.5 * yy + np.random.randint(0,100,(20,20))
#构建成特征、值的形式
X, Z = np.column_stack((xx.flatten(),yy.flatten())), zz.flatten()
#线性回归分析
regr = linear_model.LinearRegression()
regr.fit(X, Z)
#预测的一个特征
x_test = np.array([[15.7, 91.6]])
print regr.predict(x_test)
#画图可视化分析
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.scatter(xx, yy, zz) #真实点
#拟合的平面
ax.plot_wireframe(xx, yy, regr.predict(X).reshape(20,20))
ax.plot_surface(xx, yy, regr.predict(X).reshape(20,20), alpha=0.3)
plt.show()
输出如下图所示:



四. Pizza数据集一元和多元线性回归分析


完整代码如下:

# -*- coding: utf-8 -*-
"""
Created on Sun Nov 26 23:31:16 2017

@author: yxz15
"""

# -*- coding: utf-8 -*-
from sklearn.linear_model import LinearRegression

#数据集 直径、价格
x = [[5],[6],[7],[8],[10],[11],[13],[14],[16],[18]]
y = [[6],[7.5],[8.6],[9],[12],[13.6],[15.8],[18.5],[19.2],[20]]
print x
print y

clf = LinearRegression()
clf.fit(x,y)
pre = clf.predict([12])[0]
print(u'预测直径为12英寸的价格: $%.2f' % pre)
x2 = [[0],[12],[15],[25]]
y2 = clf.predict(x2)

import matplotlib.pyplot as plt
import numpy as np

plt.figure()
plt.axis([0,25,0,25])
plt.scatter(x,y,marker="s",s=20)
plt.plot(x2,y2,"g-")

#导入多项式回归模型
from sklearn.preprocessing import PolynomialFeatures
xx = np.linspace(0,25,100) #0到25等差数列
quadratic_featurizer = PolynomialFeatures(degree = 2) #实例化一个二次多项式
x_train_quadratic = quadratic_featurizer.fit_transform(x) #用二次多项式多样本x做变换
X_test_quadratic = quadratic_featurizer.transform(x2)
regressor_quadratic = LinearRegression()
regressor_quadratic.fit(x_train_quadratic, y)
xx_quadratic = quadratic_featurizer.transform(xx.reshape(xx.shape[0], 1))# 把训练好X值的多项式特征实例应用到一系列点上,形成矩阵

plt.plot(xx, regressor_quadratic.predict(xx_quadratic),
         label="$y = ax^2 + bx + c$",linewidth=2,color="r")
plt.legend()
plt.show()
输出如下图所示:

四次方拟合,核心代码如下:

#导入多项式回归模型
from sklearn.preprocessing import PolynomialFeatures
xx = np.linspace(0,25,100) #0到25等差数列
quadratic_featurizer = PolynomialFeatures(degree = 4) #实例化一个二次多项式
x_train_quadratic = quadratic_featurizer.fit_transform(x) #用二次多项式多样本x做变换
X_test_quadratic = quadratic_featurizer.transform(x2)
regressor_quadratic = LinearRegression()
regressor_quadratic.fit(x_train_quadratic, y)
xx_quadratic = quadratic_featurizer.transform(xx.reshape(xx.shape[0], 1))# 把训练好X值的多项式特征实例应用到一系列点上,形成矩阵

plt.plot(xx, regressor_quadratic.predict(xx_quadratic),
         label="$y = ax^4 + bx + c$",linewidth=2,color="r")
plt.legend()
plt.show()
输出如下图所示:


希望文章对你有所帮助,尤其是我的学生,如果文章中存在错误或不足之处,还请海涵。给绿幺准备惊喜中~
(By:Eastmount 2017-11-26 深夜12点  http://blog.csdn.net/eastmount/ )


作者:Eastmount 发表于2017/11/26 23:40:33 原文链接
阅读:68 评论:0 查看评论
Viewing all 35570 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>