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

前端基础-08-数据类型高阶函数

$
0
0

前端基础-数据类型高阶函数

1.六大数据类型

  • number 数字类型
  • string 字符串类型
  • boolean boolean类似
  • function 函数
  • undefined 默认赋值
  • object 对象

2.number数字操作

#number数字
    在js里面的小数和整数统一都是数字,-2^53-2^53,超出范围之后
    精度就会不准确

#parseInt(解析的参数)——将参数转换为数字,整数部分遇到不
是数字就停
var  n="5.16"; #输出5
alert(parseInt(n))

#parseFloat()——将参数转换为数字,不是数字就停,否则直到
小数部分遇到不是数字就停
var  n="5.1613safd";  #输出5.1613
alert(parseFloat(n))

# Num.toFixed(n)——四舍五入保留n位小数
alert(parseFloat(n).toFixed(2))  #toFixed(2) 保留两位小数,四舍五入

#NaN(Not a Number)
            NaN 不等于自己

alert(NaN == NaN);#false

#系统函数
alert(Math.pow(2,3));#2^3 幂运算
alert(Math.round(5.5));#四舍五入(取整)
alert(Math.ceil(0.2));#向上取整
alert(Math.ceil(-0.2));# 0
alert(Math.floor(-2.9));#向下取整
alert(Math.random());#随机数 [0,1)
var x = Math.random();
alert(x*10 + 10);
alert(Math.PI);
var a = Math.max(25,13,10,-5); #求一组数字中的最大数
alert(a);
var b = Math.min(-25,3,20);#求一组数字中的最小数

alert(b);
alert(Math.abs(-10));#求绝对值

3.字符串

#索引、下标、偏移量——从0开始

#str[index];——通过索引取字符串
alert(str[0]);
#str[0] = "y";//只能读,不能写(修改)

#str.length;——获取长度  空格也算
alert(str.length);

#value.toString();——转换字符串
var a = 456;
alert(a.toString());

#str.substring();——截取字符串 会比较参数值的大小,
小的参数在前面,负数变为0
var a="java"
alert(str.substring(2,3));#v
alert(str.substring(2,-1));#等价于(0,2)

#str.slice()——切片,不会交换位置,负数从右到左数
var  str="python";
alert(str.slice(2,4));
var  str="python";
alert(str.slice(-4,-2)); #从后面开始算,切片

#str.split()——字符串切割,返回数组
var  str="You need python";
alert(str.split(" ")[0]); #输出You

#str.indexOf——查找字符串,成功返回索引,反之返回-1
var  str="You need python";
alert(str.indexOf(" ")); #查找第一个是空格的元素位置 是3  
alert(str.indexOf(" ",5)); #从索引是5的位置开始找

#str.toUpperCase()——全部转换大写
var  str="You";
alert(str.toUpperCase());#YOU

#str.toLowerCase()——全部转换小写
var  str="You need python";
alert(str.toLowerCase());

4.数组

#定义一个数组
var arr = ["a","b","c","d"];
arr.length #数组的长度
arr[2]#取值
arr[2] = "f"; #数组赋值 
arr.join(",");  #输出a,b,c,d

#以创建对象的形式 创建数组
var arr = new Array();
arr[0]="a"

var arr = ["龙虾","周黑鸭","绝味","鸡排","烧鸡"];
arr.push("湖南","长沙");#往数组后面 追加  多个
arr.unshift("北京");#往数组前面 追加  多个
arr.pop();#删除数组最后一位
arr.shift();#删除数组的第一个
arr.splice(2);#保留数组的长度为最多为2个
arr.splice(2,1);#从下标2开始 删除一位
arr.splice(2,0,"螺蛳粉");#从下标2开始 删除0位(就是不删除) 添加螺蛳粉

var arr = [2,5,4,8,1];
arr.sort();#从小到大
arr.sort().reverse();#从大到小
arr.sort(function (a,b) {
    return a - b;#排序,从小到大
    return b - a;#排序从大到小
    return -1;#顺序没有变
    return 1;#    倒叙
});

5.日期

var data = new Date();
var strap = data;#完整时间
var strap = data*1;#时间戳
var strap = data.getTime();#方法打起括号来执行  时间戳
var year = data.getFullYear();//获取年份    取值为四位数字
var month = data.getMonth()+1;//获取月份    取值为0~11之间的整数
var date = data.getDate();//获取日数    取值为1~31之间的整数
var hour = data.getHours();//获取小时数  取值为0~23之间的整数
var minutes = data.getMinutes();//获取分钟数  取值为0~59之间的整数
var seconds = data.getSeconds();// 获取秒数    取值为0~59之间的整数
var day = data.getDay();//获取周几    取值为0~6之间的整数
alert(day);

6.定时器

定时器常用的三种方法:
#第一种
setInterval(function () {//每200毫秒执行一次,循环执行
    console.log(1)
}, 200)
#第二种
setTimeout(function () {//多少毫秒执行,只会执行一次
    console.log(3)
},200)
#第三种
setInterval(fn, 1000);
function fn() {
    console.log(3);
}
#清除定时器
#清除Interval
var  num=5;
var time=setInterval(fn, 1000);
function fn() {
    num--;
    if (num==1){
        alert("已经清除了")
        clearInterval(time)//清除定时器
    }
    console.log(3);
}

#清除Timeout
var  num=5;
var time=setTimeout(fn, 1000);
function fn() {
    num--;
    if (num==1){
        alert("已经清除了")
        clearTimeout(time)//清除定时器
    }
    console.log(3);
}
作者:lianjiaokeji 发表于2017/11/18 9:03:46 原文链接
阅读:43 评论:0 查看评论

机器学习:朴素贝叶斯--Python

$
0
0

今天介绍机器学习中一种基于概率的常见的分类方法,朴素贝叶斯,之前介绍的KNN, decision tree 等方法是一种 hard decision,因为这些分类器的输出只有0 或者 1,朴素贝叶斯方法输出的是某一类的概率,其取值范围在 0-1 之间,朴素贝叶斯在做文本分类,或者说垃圾邮件识别的时候非常有效。

朴素贝叶斯就是基于我们常用的贝叶斯定理:

p(x|y)=p(y|x)p(x)p(y)

假设我们要处理一个二分类问题: c1,c2,给定一个样本,比如说是一封邮件,可以用向量 x 来表示,邮件就是一个文本,而文本是由单词构成的,所以 x 其实包含了这封邮件里出现的单词的信息,我们要求的就是,给定样本 x ,我们需要判断这个样本是属于 c1 还是属于 c2,当然,我们可以用概率表示为:

p(c1|x)>=<p(c2|x)

这个就是我们常见的后验概率。根据贝叶斯定理,我们可以得到:

p(c|x)=p(x|c)p(c)p(x)

虽然,p(x) 我们无法得知,但是我们只要求出 p(x|c)p(c), 依然可以做出判断,p(x|c) 称为似然估计,而 p(c) 称为先验概率。

接下来,看看什么是朴素贝叶斯,假设 x 的维度为 n,即 x={x1,x2,...xn}, 那么,

p(x|c)=p(x1,x2,...xn|c)

一般来说,x1,x2,...xn 不会是完全相互独立不相关的,为了求解方便,朴素贝叶斯假设这些变量 x1,x2,...xn 是相互独立,或者说conditional independent , 那么上面的表达式可以写成:

p(x|c)=p(x1,x2,...xn|c)=p(x1|c)p(x2|c)...p(xn|c)

这就是我们说的朴素贝叶斯,接下来的就是各种统计了。

我们给出一个利用朴素贝叶斯做文本分类的例子:

首先建立一个数据库:

def Load_dataset():
    postingList=[['my', 'dog', 'has', 'flea', \
                  'problems', 'help', 'please'],
                ['maybe', 'not', 'take', 'him', \
                 'to', 'dog', 'park', 'stupid'],
                ['my', 'dalmation', 'is', 'so', 'cute', \
                 'I', 'love', 'him'],
                ['stop', 'posting', 'stupid', 'worthless', 'garbage'],
                ['mr', 'licks', 'ate', 'my', 'steak', 'how',\
                 'to', 'stop', 'him'],
                ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
    classVec = [0, 1, 0, 1, 0, 1]
    return postingList, classVec 

接下来,我们建立一个字典库,保证每一个单词在这个字典库里都有一个位置索引,一般来说,字典库的大小,就是我们样本的维度大小:

def Create_vocablist(dataset):
    vocabSet = set([])
    for document in dataset :
        vocabSet = vocabSet | set(document)
    return list(vocabSet)

我们可以将样本转成向量:一种方法是只统计该单词是否出现,另外一种是可以统计该单词出现的次数。

def Word2Vec(vocabList, inputSet):
    returnVec = [0] * len(vocabList) 
    for word in inputSet :
        if word in vocabList :
            returnVec[vocabList.index(word)] = 1
        else:
            print ("the word %s is not in the vocabulary" % word)
    return returnVec
def BoW_Vec(vocabList, inputSet):
    returnVec = [0] * len(vocabList) 
    for word in inputSet :
        if word in vocabList :
            returnVec[vocabList.index(word)] += 1
        else:
            print ("the word %s is not in the vocabulary" % word)
    return returnVec

接下来,我们建立分类器:这里需要注意的是,由于概率都是 0-1 之间的数,连续的相乘,会让最终结果趋于0,所以我们可以把概率相乘转到对数域的相加:

def Train_NB(trainMat, trainClass) :
    Num_doc = len(trainMat)
    Num_word = len(trainMat[0])
    P_1 = sum(trainClass) / float(Num_doc)
    P0_num = np.zeros(Num_word) + 1
    P1_num = np.zeros(Num_word) + 1
    P0_deno = 2.0
    P1_deno = 2.0
    for i in range(Num_doc):
        if trainClass[i] == 1:
            P1_num += trainMat[i]
            P1_deno +=sum(trainMat[i])
        else:
            P0_num += trainMat[i]
            P0_deno += sum(trainMat[i])
    P1_vec = np.log(P1_num / P1_deno)
    P0_vec = np.log(P0_num / P0_deno)

    return P_1, P1_vec, P0_vec
def Classify_NB(testVec, P0_vec, P1_vec, P1):
    p1 = sum(testVec * P1_vec) + math.log(P1)
    p0 = sum(testVec * P0_vec) + math.log(1-P1)
    if p1 > p0:
        return 1
    else:
        return 0


def Text_parse(longstring):
    import re
    regEx = re.compile(r'\W*')
    Listoftokens = regEx.split(longstring)
    return [tok.lower() for tok in Listoftokens if len(tok)>0]
#    return Listoftokens

这里给出简单的测试:

test_string = 'This book is the best book on Python or M.L.\
 I have ever laid eyes upon.'

wordList = Text_parse(test_string)

Mydata, classVec = Load_dataset()

'''
Doc_list = []
Full_list = []
for i in range (len(Mydata)):
    Doc_list.append(Mydata[i])
    Full_list.extend(Mydata[i])
'''

Vocablist = Create_vocablist(Mydata)

Wordvec = Word2Vec(Vocablist, Mydata[0])

trainMat = []
for doc in Mydata:
    trainMat.append(Word2Vec(Vocablist, doc))

P_1, P1_vec, P0_vec = Train_NB(trainMat, classVec)


print Mydata
print classVec
print wordList
作者:shinian1987 发表于2017/11/18 9:17:29 原文链接
阅读:30 评论:0 查看评论

spring boot(22)-profile环境配置

$
0
0

当你在公司时,可能会用公司内网的数据库进行开发,而当你回家时,就只能用本机的数据库了。不停的修改环境配置会很麻烦,profile的作用就是同时配置多个环境,在不同的环境使用不同的配置。

properties环境配置

第五篇讲过在application.properties中进行参数配置,现在如果要配置不同环境的properties,可以使用application-{环境名}.properties。

首先配置一个application-dev.properties文件,这是dev环境,用于在家开发,使用的localhost本机数据库。

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=***
spring.datasource.password=***
再配置一个application-test.properties文件,这是test环境,在公司时使用公司的测试数据库开发。

spring.datasource.url=jdbc:mysql://公司数据库ip地址:3306/test
spring.datasource.username=***
spring.datasource.password=***

激活环境

要激活不同的环境,需要在application.properties文件中配置spring.profiles.active参数,如下激活了dev本机环境。如果你到公司去只需要将dev改成test即可 。

spring.profiles.active=dev

项目结构


application.properties用来配置spring.profiles.active和公共参数。比如公司和本机的mysql用户名密码是一样的,就可以在application.properties中统一配置,不同环境只需要配置不同mysql的url。

@Profile注解配置方式

除了properties文件,也可以在java文件中使用@Profile注解来区分不同环境的代码。
@RestController
@Profile("dev")
public class SampleController {
	{
		System.out.println("当前是dev环境");
	}
如上,@Profile的参数为dev,也就是只有spring.profiles.active=dev的时候这个类才会生效。
{......}是java初始化块,在这个类初始化时会执行块的内容。现在启动项目,在控制台启动信息中会看到以下内容。

如果将@Profile的dev修改成test,那么与当前的dev环境不匹配,也就不会初始化这个类,不会在控制台打印这句话,除非激活test环境。
@Profile注解也可以用在方法上,仅对某一个方法生效
作者:wangb_java 发表于2017/11/18 10:00:24 原文链接
阅读:19 评论:0 查看评论

数据结构应该偏理论还是偏实践?

$
0
0

【前言】本文以数据结构为例。但关于理论和实践的关系,以及学习路线,对其他课程、学科也有参考价值。

【正文】
  有学生问:“数据结构应该偏理论还是偏实践?”
  这是一个非常好的问题。
  我知道,他是在学数据结构中有压力了,想去偏一偏。
  这是一个选择问句,但若回答,还真不是顺着这个道二选一就了事。
  
  (一)理论和实践
  先分析一下何为理论,何为实践。
  理论是从大量应用中提取出来的共性的特征、原理。理论层次的知识,是大家智慧的结晶。对当下的学习者而言,就是前人的积累。理论这种间接经验的学习,可以让我们在很短的时间之间,接受前人需要几十年,甚至成百上千年的积累。
  理论,是在学习中,尤其中在大学的学习中,极其重要的部分。不掌握专业中基本的理论,上大学的成色不足。只凭着有限的直接经验和体验,而放弃前人的积累,亏大了。不拿,白不拿啊。
  然而,理论的学习,却常常是枯燥的。学习者,不,往往是欲入门而不得的初学者,会由于这种枯燥而急燥、心焦,甚至产生厌恶,萌生放弃的念头。
  这不是理论的错,是学法的错。
  理论本来是鲜活的,理论的学习也可以是鲜活的。
  如何鲜活起来?
  需要实践来出场了。
  在学理论中,要融入实践。从实践中,得到的是直接经验,是属于自己的体验、体会。
  在大学生阶段学习过程中做的实践,可以算是对知识初步的应用。通过实践的行为和过程,你会发现理论的确是在指导着实践,理论这个东东真是有用啊。在思考实践问题的解决方案时,你会发现理论传达的那个思维方式在起作用了。甚至于,解决实际问题时,理论里的那些个公式、算法直接拿过来用,真省事!
  有了高度概括的理论,具体问题的解决,变得很容易的样子。
  有了实践,再也不会说“老师教的这些东西全没用”。去除了这个心魔,学习的主动性,这个学习的法宝,自然就留在你身边了。
  实践,其实是我们学习的最终目的。从这个角度,理论是阶梯。最终我们有创新的实践,也会进入到理论体系中,成为后人可学的宝贵的间接经验。你在达成自己目标的过程中的间接成果,再次成为后人的阶梯。
  实践,也是我们学习的手段。不去结合实践的理论学习,注定是枯燥的。有个别的人,在纯理论堆里得心应手,那自有他的道道。但是,现在对于感觉理论枯燥的人,你缺的,是实践。
  
  (二)理论和实践的层次
  现代科学体系变得越来越庞大,形成了各个分支,每个分支中又形成了多个层次。
  这个层次的存在,使得理论和实践没有了绝对的区分。
  换句话说,同一个知识点,在有人眼里是理论,有人眼里是实践。说它是实践的人,是站在学科更高层次的;说它是理论的,常是刚入门者。
  小学时学1+1,其实已经进入到符号思维的层面了。这是理论,因为你再不用具体到1个苹果或1个小朋友的层面了。而到了小学高年级学到a+b的时候,学运算的交换律、结合律之类的,1+1不就是很具体的应用了吗?
  说大学。高等数学、线性代数,数学类的科目,是理论。但若学一下泛函分析、近世代数,那些分明很具体了呵。显然,学泛函、近代前,先学高数、线代。
  说计算机类专业的学习。数据结构、数据库原理,初学发现是理论,大部分人也这么说。联系离散数学想一想,这不全是应用层面的实践吗?
  而数据结构,确是理论。这是站在程序设计的角度说的。做各种项目,用各种语言,随便你要解决个什么问题,数据该如何表示,如何存储,在特定存储结构下,基本运算该如何实现,这些都是真实应用需要的基石。
  前面说的在纯理论堆里得心应手的个别人,是将你眼中的理论当应用的人。
  理论和实践有层次,但千万不要理解偏为社会分工有高低。随着长大,我们总要在行业、学科中的某个层面找到自己的位置。社会的需要,每个人的生存、发展,需要有多个位置,各个位置上都需要有人做事。哪个层面的工作做得得心应手了,那都是专家。
  不管哪个层面,都需要娴熟于自己那个层面的实践,要熟悉直接支撑自己工作的那个层面的理论,对这个理论背后的理论有一点点了解,直到你再也不必了解的那个理论的理论层面。
  是的,随着学习的进展,自己要成为专家,成为高手的那个层就要定下来了。对你而言,何为理论,何为实践也就定下来了。
  
  (三)数据结构该如何学
  大学是专业学习的入门阶段。
  数据结构,是大学专业课中的“专业基础课”,这是大家的共识。这样的表述,意味着数据结构就是承上启下的。若说学某语言及其程序设计是1+1的话,数据结构就是a+b,后面还有解析几何、微积分。有了程序设计的直接体验,可以学数据结构,学数据结构中的理论,做数据结构层面的实践。等学过了数据结构了,操作系统、网络原理之类的课中,张口就是堆、栈、树、图,老师都不用多解释一句。
  数据结构是理论,也是实践。
  数据结构不是理论,也不是实践。
  看你站在哪个角度讲。
  在学习数据结构的时候,理论和实践要同步上。每一种逻辑结构,要解决的问题,数据的表达、存储,基本运算的实现,算法的复杂性,是要学的。光看懂书,能说明白不算,把这些东西能变成代码,这是科班人员的基本功。基本功是靠练才能出来的。
  为了学的感受好一些,为了能解答所学知识用在哪儿,怎么用,用所学解决点问题,也是应该的。这些东西要靠着老师讲,一是讲不了,二是他讲了不算,你做了才行。
  据此,对于要成为计算机科学与技术的科班人员而言,数据结构中的理论和实践,两手都要抓,两手都要硬。
  说“我会实践”就行了的,我觉得可惜。能做出来是一回事,你要清楚到底做得好不好,怎样做才是好的,是需要点理论的。会做的,一抓一大把,我们缺少的,是能做好的。
  说“我把书看懂了就行”的,我表示怀疑,可以混个及格还可以。经常,做一做实践,你会发现你未必真懂了。
  产生“偏理论”或者“偏实践”念头的同学,是遇到困难了。是进大学后,在学习上欠了账的。
  知道要实践,但一看代码就头疼,程序设计的实践没做够,甚至程序设计语言层面的知识都不过关。知道理论很重要,但学不下去,是理论之前的理论不扎实,思维跟不过来。而不扎实的理论,和没有经过实践也脱不了干系。
  这也就是我一直呼吁同学们要用实践的方式学程序设计的原因了。程序设计,作为大学中不必有先修课就学的课程,先不必找什么理论,直接实践起来就行。
  产生“偏理论”或者“偏实践”念头的同学,紧跟课程的进度为要。因为你有欠账,所以得加倍付出努力。紧紧跟住,是因为学数据结构中的实践,也是程序设计能力提高的方式。一旦遇到突破不了的点,补程序设计中的知识点。
  要不要先把C语言学一遍再学数据结构?至少数据结构快考试了,来不及。如果需要,假期时间自己重学一遍C语言是可以的。如果你真能协调好时间,现在做也可以。就现实的情况,以能将实践做下去为原则,C语言部分则是缺啥补啥更现实。
  
  
  

作者:sxhelijian 发表于2017/11/18 10:03:16 原文链接
阅读:20 评论:0 查看评论

用户日志分析系统实战(四)

$
0
0
用户日志分析系统实战(四)

(to be done)

作者:qq_17776287 发表于2017/11/17 22:48:52 原文链接
阅读:24 评论:0 查看评论

用户日志分析系统实战(五)

$
0
0

用户日志分析系统实战(五)

(to be done)

作者:qq_17776287 发表于2017/11/18 9:55:50 原文链接
阅读:19 评论:0 查看评论

用户日志分析系统实战(六)

$
0
0

用户日志分析系统实战(六)

(to be done)

作者:qq_17776287 发表于2017/11/18 9:56:18 原文链接
阅读:22 评论:0 查看评论

MapJoin和ReduceJoin区别

$
0
0

MapJoin和ReduceJoin区别

MapJoin小表连大表

ReduceJoin大表连大表

(to be done)

作者:qq_17776287 发表于2017/11/18 11:17:10 原文链接
阅读:20 评论:0 查看评论

人工智能在教育方面应用的思考(一)

$
0
0

人工智能在教育上的应用一直是我们研究的重点和难点,在未来的日子里,盼望人工智能能在教育方面迎来更多的变革和创新!

现在我觉得重要的方向是

  1. 是基于AI的认知诊断方向,诊断学生的知识掌握状态,之后就可以有意识的辅助学生弱项知识,这块knewton,alekx做的不错;国内的情况,还是大多停留在嘴上,没有提供好的在线诊断的平台。
    这一点进行深耕,可以帮助老师和家长、学生自己实时查看自己学习情况,提高学习效率。

  2. 基于AI的自动解题,比如说现在热门的高考机器人(虽然现有企业做的水分较大,但知名的如allenai、微软和腾讯等都在积极拓展该领域,并在2017年发表了几篇顶级论文),就可以做自动数学题求解,生成解题步骤,辅助学生学习,这块国外wolfram alpha做得很不错,但国内至少没看到很好处理中文数学题目的项目。
    这一点的拓展在于补助教师解题判卷,减轻了老师们的改大量作业的负担,同时也能统计学生的做题情况,在线生成学生的错题集等。

  3. 三的话算是一小方向,针对方向二的,即数学公式符号识别,只有很好的识别出数学公式才能帮助方向二更好的发展。现在扩展来看可以做图文加公式符号的混合图文识别,研究高精度的识别出学生的手写体的解题内容加公式图表的识别,这可以为全学习过程的在线化提供莫大的帮助,有效的上传学生的学习过程,可以为以后学生的学习情况诊断和知识的查缺补漏提供重要的数据支持。
    这一点为方向二打基础,做到学生做的题目及其学生解题过程都可以记录在案,分析学生解题过程,更多的发现学生的知识点的不足。

现有的科大讯飞的智课网等机构积极拓展自己的教育领域,在在线课程课务管理/查询考试成绩/在线判卷/将语音识别应用于考试等领域进行研发拓展。在有了大量的流量基础上,扩展教辅培训市场,做课程进行收费。这其实和作业帮/猿题库/学霸君等类似,招好老师,研发好课程,赚取好的名声,让家长觉得对自己孩子很有价值,进而您懂的~但学生往往受家长要求进行学习,孩子们往往就在白天上学校课,网上上培训课之间游走~

提供点拓展资料:
http://www.msra.cn/zh-cn/news/features/computer-problem-solving-system-20170228 数学解题方向的文章

https://github.com/albertstartup/wordproblems-dataset 代数数学题数据集

http://cat.prhlt.upv.es/mer/ 数学符号识别部分文章

http://www.cs.bham.ac.uk/research/groupings/reasoning/sdag/icdar13-comp/index.html 数学符号识别数据集

Demo:
在线诊断:
https://www.knewton.com/
https://www.aleks.com/

在线解题:
http://euclid.allenai.org/
https://www.wolframalpha.com/

公式识别:
http://cat.prhlt.upv.es/mer/

作者:reallocing1 发表于2017/11/18 11:51:23 原文链接
阅读:3 评论:0 查看评论

设计模式--观察者模式

$
0
0

观察者模式

场景

自从小张上次使用了策略模式,游戏增加了很多武器营收显著增加。产品部门计划增加游戏中用户之间的互动。如果用户关注了另一个用户,被关注用户有新的游戏动态,关注者会及时收到消息。

由于小张上次表现的不错,老王准备继续把这个重任交给小张。

小张的需求理解

这个需求,本质就是被关注者的最新动态要及时发送给关注者。小张仔细思考,发现这个需求和现实生活中订阅报纸的场景很相像。

现实生活中的订阅报纸

订阅报纸流程图:

订阅报纸流程图

小张这次没有着急开始编码,分析了需求并且找到了现实生活中的真实场景,回想起上次了解 策略模式时看到了设计模式的定义:

设计模式是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。
设计模式并不直接用来完成代码的编写,而是描述在各种不同情况下,要怎么解决问题的一种方案。设计模式能使不稳定依赖于相对稳定,具体依赖于相对抽象,避免会引起麻烦的紧耦合,以增强软件设计面对并适应变化的能力。

既然设计模式是反复出现问题的解决方案,那么现实生活中是否还有相同的业务场景。小张开始仔细思考现实生活中接触到的场景。

现实生活中的更多场景

  • 微信订阅公众号
  • 微信朋友圈(会看到好友的动态,并且可以屏蔽不看)
  • 订阅博客
  • 订牛奶

    。。。。。

观察者模式

小张带着自己的思考,向经验丰富的老王求教。

老王:小张,现在进步很进步很快啊,这次这个需求在现实生活中有很多应用场景,观察者模式就是解决这个场景的方案。


小张:观察者模式?具体是如何实现的呢?

老王:小张啊,师傅领进门,修行看个人,既然你已经知道了需要用观察者模式来实现这个需求,那么就要利用网络的资源,去进行学习。
我们程序员需要学的东西很多,往往别人只能给你点拨一下,具体的了解还是要靠 百度谷歌stackoverflow来进行深入的学习,如果要系统的学习,你可以买上几本经典的书。

小张:明白,感谢王哥的指导。
小张开始在网络上疯狂的了解观察者模式,经过一个上午的了解,小张准备开始编码。

小张的实现

具体的代码

/**
 * 观察者接口
 * 也就是这个场景的:关注者
 */
interface Observer{

    public  void follower(Subjetct subjetct);//关注
    public void receiveDynamic(String message);//接受新的动态
}

/**
 * 主题接口
 * 也就是这个场景的:被关注者
 * 当它有新的动态会及时推送到它的关注者
 */
interface Subjetct{
     List<Observer> observerList = new ArrayList<Observer>();
    public void Follower(Observer observer);//增加关注者
    public void haveNewDynamic(String message);//发送新的动态
}

/**
 * 关注者一
 */
class FollowerOne implements  Observer{

    private Logger logger = LoggerFactory.getLogger(FollowerOne.class);

    public void follower(Subjetct subjetct) {
        subjetct.Follower(this);
    }

    public void receiveDynamic(String message) {
        logger.info("关注者一收到了新的动态:"+message);
    }
}

/**
 * 关注者二
 */
class FollowerTwo implements  Observer{

    private Logger logger = LoggerFactory.getLogger(FollowerTwo.class);

    public void follower(Subjetct subjetct) {
        subjetct.Follower(this);
    }

    public void receiveDynamic(String message) {
        logger.info("关注者二收到了新的动态:"+message);
    }
}

/**
 * 主题实现
 * 具体的一个对象
 * 可以被关注,并且有新的动态会通知自己关注者
 */
class Followed implements  Subjetct{

    private Logger logger = LoggerFactory.getLogger(Followed.class);

    //private List<Observer> observerList = new ArrayList<Observer>();

    public void Follower(Observer observer){
        observerList.add(observer);
    }

    public void haveNewDynamic(String message){
        logger.info("被关注着有新的动态:"+message);
        for(Observer observer :observerList){
            observer.receiveDynamic(message);
        }
    }

}

/**
*测试类,看输出效果
**/
class ObserverTest{
     public static void main(String[] args) {

        Subjetct subjetct = new Followed();
        Observer followerone = new FollowerOne();
        Observer followerTwo = new FollowerTwo();
        followerone.follower(subjetct);
        followerTwo.follower(subjetct);

        subjetct.haveNewDynamic("我买了新的武器");

    }
}

类图

观察者模式

是否少了点什么

目前的实现,只能实现关注,但是如果关注者要取消关注呢?相信聪明的你是知道如何做的。(提供一点思路在主题接口,增加一个方法,能够从集合里移除关注者)

观察者模式

观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

要点

  • 观察者模式定义了对象之间一对多的关系
  • 主题(也就是可观察者)用一个共同接口来更新观察者
  • 观察者与可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口
  • 有多个观察者时,不可以依赖特点的通知次序
  • swing大量使用观察者模式,许多GUI框架也是如此.
作者:u013565163 发表于2017/11/18 13:18:11 原文链接
阅读:3 评论:0 查看评论

Codeforces Round #446 (Div. 2) A-C 题解

$
0
0

第一次CF涨分啊,真**不容易。

A. Greed
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Jafar has n cans of cola. Each can is described by two integers: remaining volume of cola ai and can's capacity bi (ai  ≤  bi).

Jafar has decided to pour all remaining cola into just 2 cans, determine if he can do this or not!

Input

The first line of the input contains one integer n (2 ≤ n ≤ 100 000) — number of cola cans.

The second line contains n space-separated integers a1, a2, ..., an (0 ≤ ai ≤ 109) — volume of remaining cola in cans.

The third line contains n space-separated integers that b1, b2, ..., bn (ai ≤ bi ≤ 109) — capacities of the cans.

Output

Print "YES" (without quotes) if it is possible to pour all remaining cola in 2 cans. Otherwise print "NO" (without quotes).

You can print each letter in any case (upper or lower).

Examples
input
2
3 5
3 6
output
YES
input
3
6 8 9
6 10 12
output
NO
input
5
0 0 5 0 0
1 1 8 10 5
output
YES
input
4
4 1 0 3
5 2 2 3
output
YES
Note

In the first sample, there are already 2 cans, so the answer is "YES".


大水题,我一开始还在天真的按照剩余空间排序,醉了。
就是所有饮料能不能倒入两个瓶子内,找到两个最大的,判断一下就ok。
代码实现:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<cstdio>
#define ll long long
#define mset(a,x) memset(a,x,sizeof(a))

using namespace std;
const double PI=acos(-1);
const int inf=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int mod=1e9+7;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;}
ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}
struct node{
	int x;
	int y;
	int c;
}p[100005];
int a[100005],b[100005];

int main()
{
	int n,i,j,k;
	while(cin>>n)
	{
		mset(p,0);
		for(i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
		}
		for(i=0;i<n;i++)
		{
			scanf("%d",&b[i]); 
		}
		long long ans=0;
		for(i=0;i<n;i++)
		ans+=a[i];
		
		sort(b,b+n);
		ll sum=b[n-1]+b[n-2];
		if(sum>=ans)
		cout<<"YES"<<endl;
		else
		cout<<"NO"<<endl;
	}
	return 0;
}

B. Wrath
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Hands that shed innocent blood!

There are n guilty people in a line, the i-th of them holds a claw with length Li. The bell rings and every person kills some of people in front of him. All people kill others at the same time. Namely, the i-th person kills the j-th person if and only if j < i and j ≥ i - Li.

You are given lengths of the claws. You need to find the total number of alive people after the bell rings.

Input

The first line contains one integer n (1 ≤ n ≤ 106) — the number of guilty people.

Second line contains n space-separated integers L1, L2, ..., Ln (0 ≤ Li ≤ 109), where Li is the length of the i-th person's claw.

Output

Print one integer — the total number of alive people after the bell rings.

Examples
input
4
0 1 0 10
output
1
input
2
0 0
output
2
input
10
1 1 3 0 0 0 2 1 0 3
output
3
Note

In first sample the last person kills everyone in front of him.


神坑,最后几分钟过的B,迷之WA,最后不得已用了树状数组,单点查询区间最小值才过的,话说,别人都是几行模拟,怀疑人生。。
为确保压入的数非负,可以压入一个0或1作为最小。

代码实现:
#include<cstdio>  
#include<cstring>  
#include<algorithm> 
#include<iostream> 
#define ll long long  
  
using namespace std;  
  
const int INF=0x3f3f3f3f;
const long long MAX=1<<22;
struct tree{
	int n;
	int a[MAX],Max[MAX],Min[MAX]; //Max维护最大值 ,Min最小
	void init(int N)
	{
		n=N;
		for(int i=0;i<=N;i++)
			Max[i]=-(Min[i]=INF);
	}
	void update(int x,int num)//单点更新 
	{
		a[x]=num;
	    while(x<=n)
	    {
	        Min[x]=Max[x]=a[x];
	        int lx=x&-x;
	        for(int i=1;i<lx;i<<=1)
	        {
	        	Max[x]=max(Max[x],Max[x-i]);
	            Min[x]=min(Min[x],Min[x-i]);
			}
	        x+=x&-x;
	    }
	}
	int Qmax(int x,int y)//[x,y]最大值
	{  
	    int ans=-INF; 
	    while(y>=x)  
	    {  
	        ans=max(a[y], ans);  
	        y--;
	        for(;y-(y&-y)>=x;y-=(y&-y))
	            ans=max(Max[y],ans);  
	    }  
	    return ans;  
	}
	int Qmin(int x, int y)
	{  
	    int ans=INF;  
	    while(y>=x)
	    {
	        ans=min(a[y],ans);
	        y--;
	        for(;y-(y&-y)>= x; y-=(y&-y)  )
	            ans=min(Min[y],ans);  
	    }
	    return ans;
	}  
}C;
int a[1000005];
  
int main()
{  
    int q,i,n,j;  
    while (scanf("%d",&n) != EOF)
	{  
        C.init(n); 
        for (i = 1; i<=n; i++)
		{  
            scanf("%d",&a[i]);
            C.update(i,max(i-a[i],1));
        } 
        int ans=1;
        for(i=n-1;i>=1;i--)
        {
        	if(i<C.Qmin(i+1,n))
        	ans++;
		}
		cout<<ans<<endl;
    }  
    return 0;  
}  

C. Pride
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You have an array a with length n, you can perform operations. Each operation is like this: choose two adjacent elements from a, say xand y, and replace one of them with gcd(x, y), where gcd denotes the greatest common divisor.

What is the minimum number of operations you need to make all of the elements equal to 1?

Input

The first line of the input contains one integer n (1 ≤ n ≤ 2000) — the number of elements in the array.

The second line contains n space separated integers a1, a2, ..., an (1 ≤ ai ≤ 109) — the elements of the array.

Output

Print -1, if it is impossible to turn all numbers to 1. Otherwise, print the minimum number of operations needed to make all numbers equal to 1.

Examples
input
5
2 2 3 4 6
output
5
input
4
2 4 6 8
output
-1
input
3
2 6 9
output
4
Note

In the first sample you can turn all numbers to 1 using the following 5 moves:

  • [2, 2, 3, 4, 6].
  • [2, 1, 3, 4, 6]
  • [2, 1, 3, 1, 6]
  • [2, 1, 1, 1, 6]
  • [1, 1, 1, 1, 6]
  • [1, 1, 1, 1, 1]

We can prove that in this case it is not possible to make all numbers one using less than 5 moves.


本来C题可以搏一搏,单车变摩托。但B题实在费心,最后导致没时间做C题,菜是原罪啊。没什么好说的,就是一个找1的过程,找到1就一切都解决了。

代码实现:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<cstdio>
#define ll long long
#define mset(a,x) memset(a,x,sizeof(a))

using namespace std;
const double PI=acos(-1);
const int inf=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int mod=1e9+7;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;}
ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}
int map[maxn];

int main()
{
	int i,j,k,n;
	while(cin>>n)
	{
		int sum=0;
		for(i=0;i<n;i++)
		{
			cin>>map[i];
			if(map[i]==1)
			sum++;
		}
		if(sum)
		{
			cout<<n-sum<<endl;
			continue;
		}
		int minn=n+1;
		for(i=0;i<n;i++)
		{
			int temp=map[i];
			for(j=i+1;j<n;j++)
			{
				temp=gcd(temp,map[j]);
				if(temp==1)
				break;
			}
			if(j!=n)
			{
				minn=min(minn,j-i);
			}
		}
		if(minn==n+1)
		cout<<"-1"<<endl;
		else
		cout<<minn+n-1<<endl;
	}
	return 0;
}


作者:Ever_glow 发表于2017/11/18 13:53:50 原文链接
阅读:0 评论:0 查看评论

linuxPci驱动获取指定设备bus、device以及devfn数据方式

$
0
0

在vxworks系统中,调用pciFindDevice()函数可以直接获取到指定设备的bus、deviceNo以及devfn数据信息。相对于linux系统,vxworks编写驱动相对简单一些。

linux系统下bus、deviceNo以及devfn数据由驱动内部函数使用 (编写驱动过程中这些数据几乎用不到),并且没有提供明确的接口,需要我们自己分析驱动函数调用这些数据的方式。

首先在Terminal输入: lspci -vmmD;
这里写图片描述
我们看到设备信息第一行Slot:显示的这些信息,0000表示设备域,02表示bus信息,05表示deviceNo信息,0表示devfn信息;

了解到要得到数据信息后,开始追踪Pci相关文件,首先跟踪到linux/pci.h头文件找到
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#define PCI_FUNC(devfn) ((devfn) & 0x07),

根据定义名称我们知道 PCI_SLOT表示PCI槽,PCI_FUNC表示PCI函数信息(或者称为描述信息),我们得到了deviceNo和devfn的转换方法,
下面继续跟踪找到struct pci_dev结构体,结构体内找到了unsigned int devfn; , 到这里可以确定devfn和deviceNo就是用这个变量转换过来的,
现在还需要得到bus号,在pci_dev结构体中没有定义bus变量,说明我们的设备bus号应该不能直接获取到,
继续检查pci_dev结构体发现struct pci_bus bus; / bus this device is on /,看到这个注释明白了我们要找的设备bus号在pci_bus结构体内 , 跟踪 pci_bus结构体 找到unsigned char number; / bus number */。

  现在我们知道这些数据的获取方式,想要获取到数据需要用到struct pci_dev *dev指针。Pci入口函数static int __init pci_probe(struct pci_dev *dev, const struct pci_device_id *id)第一参数就是我们要用到的指针数据,结合上一篇的Pci驱动实例来描述具体实现方式,下面贴上代码:

define DevName “test”

define ClassName “class_test”

define VendorID 0xFA01

define DeviceID 0x1234

unsigned char bus;//增加bus号定义
unsigned int deviceNo;
unsigned int devfn;

struct class *mem_class;
struct Pci_Test
{
struct cdev _cdev;
dev_t dev;
char msi_enabled;
}*pci_test;

static int Test_open(struct inode *inode,struct file *filp)
{
return 0;
}

static int Test_release(struct inode *inode,struct file *filp)
{
return 0;
}

static struct file_operations test_fops = {
.owner = THIS_MODULE,
//.ioctl = Test_ioctl,
.open = Test_open,
.release = Test_release,
};

//字符驱动
static init_chrdev(struct Pci_Test *test_ptr)
{
int result = alloc_chrdev_region(&test_ptr->dev, 0, 2, DevName);
if (result < 0)
{
printk(“Err:failed in alloc_chrdev_region!\n”);
return result;
}

mem_class = class_create(THIS_MODULE,ClassName);// /dev/ create devfile 
    if (IS_ERR(mem_class))
    {
    printk("Err:failed in creating class!\n");
}
device_create(mem_class,NULL,test_ptr->dev,NULL,DevName);

cdev_init(&test_ptr->_cdev,&test_fops);
test_ptr->_cdev.owner = THIS_MODULE;
test_ptr->_cdev.ops = &test_fops;//Create Dev and file_operations Connected
result = cdev_add(&test_ptr->_cdev,test_ptr->dev,1);
return result;

}

//PCI驱动入口函数 在这个函数中增加bus、device和devfn数据获取方法
static int __init pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int rc = 0;
pci_test = dev;
pci_set_drvdata(dev, pci_test);
//在这里创建字符设备驱动
rc = init_chrdev(pci_test);
if (rc) {
dev_err(&dev->dev, “init_chrdev() failed\n”);
return -1;
}

rc = pci_enable_device(dev);
    if (rc) {
        dev_err(&dev->dev, "pci_enable_device() failed\n");
        return -1;
    } 

rc = pci_request_regions(dev, DevName);
    if (rc) {
        dev_err(&dev->dev, "pci_request_regions() failed\n");
        return -1;
    }

    pci_set_master(dev);
    rc = pci_enable_msi(dev);
if (rc) {
        dev_info(&dev->dev, "pci_enable_msi() failed\n");
        pci_test->msi_enabled = 0;
    } else {
        dev_info(&dev->dev, "pci_enable_msi() successful\n");
        pci_test->msi_enabled = 1;
}

//在这里增加获取bus、deviceNo和devfn数据的方法
bus = dev->bus->number;
deviceNo = (((dev->devfn) >> 3 ) && 0x1f);
devfn = ((dev->devfn) && 0x07);

return rc;
}

static void __exit pci_remove(struct pci_dev *dev)
{
if (0 != mem_class)
{
device_destroy(mem_class,pci_test->dev);
class_destroy(mem_class);
mem_class = 0;
}

pci_test = pci_get_drvdata(dev);
    cdev_del(&pci_test->_cdev);
    unregister_chrdev_region(pci_test->dev, 1);
pci_disable_device(dev);

    if(pci_test) {
        if(pci_test->msi_enabled) {
                pci_disable_msi(dev);
                pci_test->msi_enabled = 0;
            }
    }

    pci_release_regions(dev);

}

static struct pci_device_id pci_ids[] = {
{ PCI_DEVICE( VendorID, DeviceID) },
{ 0 }
};

static struct pci_driver driver_ops = {
.name = DevName,
.id_table = pci_ids,
.probe = pci_probe,
.remove = pci_remove,
};
//驱动模块入口函数
static int Test_init_module(void)
{
int rc = 0;
pci_test = kzalloc(sizeof(struct Pci_Test), GFP_KERNEL);
//配对设备以及注册PCI驱动,如果找到对应设备调用PCI入口函数
rc = pci_register_driver(&driver_ops);
if (rc) {
printk(KERN_ALERT “: PCI driver registration failed\n”);
}

return rc;

}

static void Test_exit_module(void)
{
pci_unregister_driver(&driver_ops);
kfree(pci_test);
}
module_init(Test_init_module);
module_exit(Test_exit_module);
MODULE_AUTHOR(DevName);
MODULE_LICENSE(“GPL”);

上一篇Pci驱动调用字符设备驱动方式:http://blog.csdn.net/a29562268/article/details/78446178

作者:a29562268 发表于2017/11/17 22:01:05 原文链接
阅读:27 评论:0 查看评论

机器学习: Logistic Regression--python

$
0
0

今天介绍 logistic regression,虽然里面有 regression 这个词,但是这其实是一种分类的方法,这个分类方法输出的也是 0-1 之间的一个数,可以看成是一种概率输出,这个分类器利用一种 BP 迭代和随机梯度下降的方法来训练求得参数和建立分类模型。

首先来看看这个分类器用到的主要函数,即 sigmoid 函数:

y=σ(x)=11+ex

这个函数有一个很好的特性,就是它的导数,

yx=σ(x)(1σ(x))

下面看看,如何利用这个函数来做分类,假设样本为向量 x, 经过权重系数 w 以及 bias 的转换,变成 u=wTx+b,再经过 sigmoid 函数的转换,最终输出一个预测概率 y=σ(u) , 样本的 ground truth 为 t, 则预测值与真实 label 之间的误差可以用最小均方误差表示:

e=12(yt)2

我们可以通过不断的调整 wb 让预测值和真实 label 之间逐渐接近,根据链式法则,我们可以得到:

ew=eyyuuw

而每一部分的偏导数都可以求得:

ey=yt
yu=σ(u)(1σ(u))
uw=x

根据求得的偏导数,可以对权重系数进行更新:

w:=w+αew

下面给出一个用 logistic regression 做分类的例子:

import numpy as np
from sklearn import datasets

def Sigmoid(x):
    return 1.0/(1 + np.exp(-x))

def Generate_label(y, N_class):
    N_sample = len(y)
    label = np.zeros((N_sample, N_class))
    for ii in range(N_sample):
        label[ii, int(y[ii])]=1     
    return label

# load the iris data
iris = datasets.load_iris()
x_data = iris.data
y_label = iris.target
class_name = iris.target_names

n_sample = len(x_data)
n_class = len(set(y_label))

np.random.seed(0)
index = np.random.permutation(n_sample)
x_data = x_data[index]
y_label = y_label[index].astype(np.float)

train_x = x_data[: int(.8 * n_sample)]
train_y = y_label[: int( .8 * n_sample)]
test_x = x_data[int(.8 * n_sample) :]
test_y = y_label[int(.8 * n_sample) :]

train_label = Generate_label(train_y, n_class)
test_label = Generate_label(test_y, n_class)

# training process
D = train_x.shape[1]
W = 0.01 * np.random.rand(D, n_class)
b = np.zeros((1, n_class))    

step_size = 1e-1
reg = 1e-3
train_sample = train_x.shape[0]    
batch_size = 10
num_batch = train_sample / batch_size
train_epoch = 1000

for ii in range (train_epoch):

    for batch_ii in range(num_batch):

        batch_x = train_x[batch_ii * batch_size:
            (batch_ii+1) * batch_size, :]
        batch_y = train_label[batch_ii * batch_size:
            (batch_ii+1) * batch_size, :]

        scores = np.dot(batch_x, W) + b
        y_out = Sigmoid(scores)

        e = y_out - batch_y

        dataloss = 0.5 * np.sum(e*e) / batch_size
        regloss = 0.5 * reg *  np.sum(W*W)

        L = dataloss + regloss

        dscores = e * y_out * (1 - y_out) / batch_size
        dw = np.dot(batch_x.T, dscores)
        db = np.sum(dscores, axis=0, keepdims=True)

        dw += reg*W

        W = W - step_size * dw
        b = b - step_size * db

    if (ii % 10 == 0):
        print 'the training loss is: %.4f' % L

# test process
scores = np.dot(test_x, W) + b
y_out = Sigmoid(scores)

predict_out = np.argmax(y_out, axis=1)

print 'test accuracy: %.2f' % (np.mean(predict_out == test_y))
作者:shinian1987 发表于2017/11/18 15:23:45 原文链接
阅读:0 评论:0 查看评论

UIAutomator2.0详解(UIDevice篇---- 序)

$
0
0

如果我们要对Android APP进行操作,那么设备对象UIDevice是我们必须要获取。通过设备对象UIDevice,进而获取操作控件对象UIObject。

UIDevice继承于java.lang.Object。UIAutomator官方文档中,UIDevice中一共提供了62个接口方法(其中有3个,已被抛弃,不建议使用)。数量看似很多,但这些方法按照功能可细分为9类。我们也将分9个章节来总结各类方法的使用。大家可以选择自己关注的部分查看。

(1)获取UIDevice对象方法,2个
http://blog.csdn.net/daihuimaozideren/article/details/78398971

(2)获取设备或Package名称方法,4个
http://blog.csdn.net/daihuimaozideren/article/details/78430572

(3)屏幕设置操作方法,13个
http://blog.csdn.net/daihuimaozideren/article/details/78409554

(4)模拟触屏操作方法,20个
功能键&特殊页面:http://blog.csdn.net/daihuimaozideren/article/details/78436064
按键类型:http://blog.csdn.net/daihuimaozideren/article/details/78460430
点击&拖拽&滑动:http://blog.csdn.net/daihuimaozideren/article/details/78470547

(5)等待方法,5个
waitForIdle:http://blog.csdn.net/daihuimaozideren/article/details/78480167
waitForWindowUpdate:http://blog.csdn.net/daihuimaozideren/article/details/78482463
TODO~

(6)获取UIObject对象方法,4个
TODO~

(7)布局截屏文件操作方法,6个
布局:http://blog.csdn.net/daihuimaozideren/article/details/78530280
截屏:http://blog.csdn.net/daihuimaozideren/article/details/78532412

(8)监听设置方法,6个
TODO~

(9)获取/清除遍历文本方法,2个(比较尴尬,未有详细的使用说明,使用也有条件限制。下文也只记录了些质疑
http://blog.csdn.net/daihuimaozideren/article/details/78430377

作者:daihuimaozideren 发表于2017/11/18 15:26:47 原文链接
阅读:48 评论:0 查看评论

BZOJ2435: [Noi2011]道路修建

$
0
0

Description

在 W 星球上有 n 个国家。为了各自国家的经济发展,他们决定在各个国家
之间建设双向道路使得国家之间连通。但是每个国家的国王都很吝啬,他们只愿
意修建恰好 n – 1条双向道路。 每条道路的修建都要付出一定的费用, 这个费用等于道路长度乘以道路两端的国家个数之差的绝对值。例如,在下图中,虚线所示道路两端分别有 2 个、4个国家,如果该道路长度为 1,则费用为1×|2 – 4|=2。图中圆圈里的数字表示国家的编号。

这里写图片描述
由于国家的数量十分庞大,道路的建造方案有很多种,同时每种方案的修建
费用难以用人工计算,国王们决定找人设计一个软件,对于给定的建造方案,计
算出所需要的费用。请你帮助国王们设计一个这样的软件。

Input

输入的第一行包含一个整数n,表示 W 星球上的国家的数量,国家从 1到n
编号。接下来 n – 1行描述道路建设情况,其中第 i 行包含三个整数ai、bi和ci,表
示第i 条双向道路修建在 ai与bi两个国家之间,长度为ci。

Output

输出一个整数,表示修建所有道路所需要的总费用。

Sample Input

6

1 2 1

1 3 1

1 4 2

6 3 1

5 2 1

Sample Output

20

HINT

n = 1,000,000 1≤ai, bi≤n

0 ≤ci≤ 10^6

题目传送门

刚拿到题的时候,一脸凝重,已经做好了死磕2小时的准备
2分钟后…这是noi的题?不是dfs吗?别骗我啊
不对啊,他每条边都一定要用啊,要不然不联通
试试吧…

然后水掉了
垃圾题目,毁我青春

代码如下:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n;
typedef long long ll;
struct node{
    int x,y,next;
    ll d;
}a[2100000];int len,last[2100000];
void ins(int x,int y,ll d)
{
    len++;
    a[len].x=x;a[len].y=y;a[len].d=d;
    a[len].next=last[x];last[x]=len;
}
ll ans;
int tot[2100000];
void dfs(int x,int fa)
{
    tot[x]=1;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(y!=fa)
        {
            dfs(y,x);
            tot[x]+=tot[y];
            ans+=ll(a[k].d*abs(n-tot[y]-tot[y]));
        }
    }
}
int main()
{
    scanf("%d",&n);
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<n;i++)
    {
        int x,y;ll d;
        scanf("%d%d%lld",&x,&y,&d);
        ins(x,y,d);ins(y,x,d);
    }
    ans=0;
    dfs(1,0);
    printf("%lld\n",ans);
    return 0;
}

by_lmy

作者:HeroDeathes 发表于2017/11/18 15:27:20 原文链接
阅读:35 评论:0 查看评论

Unity Shader 学习笔记(12) 渲染路径(Rendering Path)

$
0
0

Unity Shader 学习笔记(12) 渲染路径(Rendering Path)

参考书籍:《Unity Shader 入门精要》
官网API:ShaderLab: Pass Tags
官网API:Rendering Paths


渲染路径

决定了光照如何应用到Unity Shader中。

Pass块内可选择的渲染路径:


前向渲染路径(Forward)

  是传统的渲染方式。
原理:渲染该对象的渲染图元,计算两个缓冲区信息(颜色缓冲区、深度缓冲区)。利用深度的缓冲判断片元是否可见,可见就更新颜色缓冲,否则就丢弃。
  如果有N个物体受M个光源影响就需要N*M个Pass。渲染引擎通常会限制每个物体的逐像素光照数目。

三种处理光照方式:
- 逐顶点处理。
- 逐像素处理。
- 球谐函数(Spherical Harmonics, SH)处理。

Unity使用的判断规则:
- 场景中最亮的平行光按逐像素处理。
- Render Mode 为 Not Important的光源,会逐顶点或者SH处理。
- Render Mode 为 Important的光源,会逐像素处理。
- 如果上面得到的逐像素光源小于Quality Setting中的逐像素光源数量,会有过更多光源以逐像素的方式进行渲染。

前向渲染两种Pass:
- Base Pass。一般一个Unity Shader定义一个(双面渲染的话两个),执行一次。
- Additional Pass。如果有N个光源影响该物体,就会执行N次。

前向渲染可以使用的内置光照变量和函数:


顶点照明渲染路径(Vertex)

  即逐顶点计算光照。硬件配置要求最低,运算性能最高,效果最差的类型,不支持逐像素效果(如:阴影、法线映射、高精度高光反射等)。

顶点照明渲染可以使用的内置变量和函数:


延迟渲染路径(Deferred)

  使用额外的缓冲区(G缓冲,Geometry-buffer),存储离摄像机最近的表明的其他信息(表面法线、位置、材质属性等)。避免前向渲染在大量实时光照下时的性能急速下降。实现就用两个Pass,与场景光源数目无关,而是和屏幕空间大小有关。

主要包含两个Pass:
1. 第一个Pass:只计算哪些片元可见(深度缓冲技术),可见的就存到G缓冲中。
2. 第二个Pass:利用G缓冲中的片元信息,计算光照。

缺点:
- 不支持真正的抗锯齿(anti-aliasing)功能。
- 不能处理半透明物体。
- 显卡必须支持MRT(Multiple Render Targets)、Shader Mode3.0及以上、深度渲染纹理以及双面的模版缓冲。

G缓冲区所包含的渲染纹理:

延迟渲染可以使用的内置变量:

作者:l773575310 发表于2017/11/18 16:31:39 原文链接
阅读:2 评论:0 查看评论

leetcode: 51. N-Queens

$
0
0

Q

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

这里写图片描述

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens’ placement, where ‘Q’ and ‘.’ both indicate a queen and an empty space respectively.

For example,
There exist two distinct solutions to the 4-queens puzzle:

[
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]
]

AC

# Time:  O(n!)
# Space: O(n)
class Solution:
    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """
        self.cols = [False] * n
        self.main_diag = [False] * (2 * n)
        self.anti_diag = [False] * (2 * n)
        self.solutions = []
        self.solveNQueensRecu([], 0, n)
        return self.solutions

    def solveNQueensRecu(self, solution, row, n):
        if row == n:
            self.solutions.append(map(lambda x: '.' * x + "Q" + '.' * (n - x - 1), solution))
        else:
            for i in xrange(n):
                if not self.cols[i] and not self.main_diag[row + i] and not self.anti_diag[row - i + n]:
                    self.cols[i] = self.main_diag[row + i] = self.anti_diag[row - i + n] = True
                    self.solveNQueensRecu(solution + [i], row + 1, n)
                    self.cols[i] = self.main_diag[row + i] = self.anti_diag[row - i + n] = False

if __name__ == "__main__":
    print Solution().solveNQueens(8)


作者:JNingWei 发表于2017/11/18 16:33:32 原文链接
阅读:11 评论:0 查看评论

leetcode: 52. N-Queens II

$
0
0

Q

Follow up for N-Queens problem.

Now, instead outputting board configurations, return the total number of distinct solutions.

这里写图片描述

AC

class Solution(object):
    def totalNQueens(self, n):
        """
        :type n: int
        :rtype: int
        """
        perms =[]
        import itertools
        for perm in itertools.permutations(range(n)):
            diag = set()
            tdiag = set()
            conflict = False
            for i, c in enumerate(perm):
                d = i+c
                td = i+n-c
                if d in diag or td in tdiag:
                    conflict = True
                    break
                diag.add(d)
                tdiag.add(td)
            if not conflict:
                perms.append(perm)
        return len(perms)


作者:JNingWei 发表于2017/11/18 16:35:11 原文链接
阅读:15 评论:0 查看评论

leetcode: 53. Maximum Subarray

$
0
0

Q

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
the contiguous subarray [4,-1,2,1] has the largest sum = 6.

More practice:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

AC

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0

        curSum = maxSum = nums[0]
        for num in nums[1:]:
            curSum = max(num, curSum + num)
            maxSum = max(maxSum, curSum)

        return maxSum


作者:JNingWei 发表于2017/11/18 16:36:59 原文链接
阅读:11 评论:0 查看评论

leetcode: 54. Spiral Matrix

$
0
0

Q

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

For example,
Given the following matrix:

[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]

You should return [1,2,3,6,9,8,7,4,5].

AC

class Solution(object):
    def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        if not matrix:
            return []

        result = []
        while len(matrix)>0:
            t = matrix.pop(0)
            matrix = self.trans(matrix)
            result += t
        return result

    def trans(self, matrix):
        return list(zip(*matrix))[::-1]


作者:JNingWei 发表于2017/11/18 16:38:39 原文链接
阅读:14 评论:0 查看评论
Viewing all 35570 articles
Browse latest View live


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