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

HDU1012 POJ1517 ZOJ1113 UVALive2083 u Calculate e【入门】

$
0
0

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 20144   Accepted: 11703   Special Judge

Description

A simple mathematical formula for e is 
e=Σ0<=i<=n1/i!

where n is allowed to go to infinity. This can actually yield very accurate approximations of e using relatively small values of n.

Input

No input

Output

Output the approximations of e generated by the above formula for the values of n from 0 to 9. The beginning of your output should appear similar to that shown below.

Sample Input

no input

Sample Output

n e
- -----------
0 1
1 2
2 2.5
3 2.666666667
4 2.708333333
...

Source


Regionals 2000 >> North America - Greater NY


问题链接HDU1012 POJ1517 ZOJ1113 UVALive2083 u Calculate e

问题简述:(略)

问题分析:这是一个简单的计算问题,控制好循环并且注意格式就可以了。

程序说明:(略)

题记:(略)

 

AC的C语言程序如下

/* HDU1012 POJ1517 ZOJ1113 UVALive2083 u Calculate e */

#include <stdio.h>

#define N 9

int main(void)
{
    double e = 2.5, f=2.0;
    int i;

    printf("n e\n");
    printf("- -----------\n");

    printf("0 1\n");
    printf("1 2\n");
    printf("2 2.5\n");

    for(i=3; i<=N; i++) {
        f *= i;
        e += 1.0 / f;

        printf("%d %.9f\n", i, e);
    }

    return 0;
}



作者:tigerisland45 发表于2017/11/14 5:44:01 原文链接
阅读:16 评论:0 查看评论

做决定,怎能让“自己”缺席

$
0
0

【来信】
  贺老师,您好,我在一次有目的的搜索中发现了您给大二软件工程学生解答的问题。仔细阅读后,决定写信给您。 同样,我也是大二软件工程的学生,混过了大一(水过了C++和数据结构),大二刚刚结束了对java的简单学习(基本掌握老师所讲),目前我属于那种不甘堕落,想要奋发图强,但是无从下手,不知道应该从何从何学起,是对c++,java进行各种方向的深入学习,还是学一些什么别的东西。身边一些比较优秀的同学,学的东西五花八门,我也无从效仿。所以向您请教,我现在需要学习什么呢,或者说我在大学期间要学习什么,下半学期在学习人机界面,所以有大把时间去学习,去编程,敲代码。我也看了学校的培养方案,但是觉得要学习一些特别的东西来提升自己,给自己创造优势。特此向您请教。

【回复】
  在保证培养方案中课程的前提下,再额外自学一些,很好的安排。而这部分的学习,没有标准答案,我怎么给你出主意呢?换个问题,你回答一下,或许能找到属于你的答案。(1)你了解专业已经一年多了,你感兴趣什么?(2)两年后你去找工作,最相找什么样的工作?从这两个问题,我觉得能够收回来些思路。

【来信】
  我学了一年多了,没啥感觉,我选专业的时候就是觉得不讨厌,不排斥,学的时候也没有那种特别热爱的感觉,但是也愿意去学。就教啥学啥。找工作这个问题还没考虑,家里人意思我先读个研。我对未来其实没有什么想法,所以才不知道学啥。但是如果什么语言或者技术应用的多,或者好找工作,我想我愿意去提前学习。技术应用比较广泛,或者有就业优势,我也愿意去掌握。

【回信】
  我可能要给你带来烦恼了。显然,你是个听话的“好孩子”。“教啥就学啥”、什么用得多就学什么,这可以让你看起来比较平稳地取得学习成就。但你要想一下,当你已经有一些基础了,没有人教你了,你该怎么办?学得多、用的多的技术和方向由于人太多没有机会了,甚至这个方向现在还好,未来不可避免地退出甚至消失了,你该怎么办?家里人想让你考研,你也如愿上了,最有价值的自主你依然没有,发展的前途在哪里?不考虑这些时,简简单单,也挺好,但我提醒你,你需要想多一些。
  哪个技术学得人多,就业好之类的,是个动态的过程,我不掌握精准的统计数据,无法给你再讲些什么,而这些你可以通过搜索得到,也不需要我整理后转你。实际上,你现在最需要的,是在做决定中,将“你自己”作为一个重要因素考虑进去的时候。一时考虑不到,就从现在开始考虑。你尚在大二,也还在基础学习的阶段,一个方向是把之前学过的水过的东西,用实践的方式学扎实了(到我的课程主页中可以找到实践的要求);第二个方向是,了解现在其他同学所学的内容,捡一个相对有好感的开始体验,以此为起点,可能会深入下去,可能会了解到更多而转方向,都是好事。不必指望学到的任何内容都是工作中直接用到的,一切都在变化,现在的学,只是为未来铺路。

作者:sxhelijian 发表于2017/11/14 6:30:55 原文链接
阅读:11 评论:0 查看评论

HDU1014 POJ1597 UVALive5492 UVA408 ZOJ1314 Uniform Generator【数论】

$
0
0

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 5584   Accepted: 2607

Description

Computer simulations often require random numbers. One way to generate pseudo-random numbers is via a function of the form 
     seed(x+1) = [ seed(x) + STEP ] % MOD



     where "%" is the modulus operator.

Such a function will generate pseudo-random numbers (seed) between 0 and MOD-1. One problem with functions of this form is that they will always generate the same pattern over and over. In order to minimize this effect, selecting the STEP and MOD values carefully can result in a uniform distribution of all values between (and including) 0 and MOD-1. 

For example, if STEP=3 and MOD=5, the function will generate the series of pseudo-random numbers 0, 3, 1, 4, 2 in a repeating cycle. In this example, all of the numbers between and including 0 and MOD-1 will be generated every MOD iterations of the function. Note that by the nature of the function to generate the same seed(x+1) every time seed(x) occurs means that if a function will generate all the numbers between 0 and MOD-1, it will generate pseudo-random numbers uniformly with every MOD iterations. 

If STEP = 15 and MOD = 20, the function generates the series 0, 15, 10, 5 (or any other repeating series if the initial seed is other than 0). This is a poor selection of STEP and MOD because no initial seed will generate all of the numbers from 0 and MOD-1. 

Your program will determine if choices of STEP and MOD will generate a uniform distribution of pseudo-random numbers. 

Input

Each line of input will contain a pair of integers for STEP and MOD in that order (1<=STEP,MOD<=100000).

Output

For each line of input, your program should print the STEP value right-justified in columns 1 through 10, the MOD value right-justified in columns 11 through 20 and either "Good Choice" or "Bad Choice" left-justified starting in column 25. The "Good Choice" message should be printed when the selection of STEP and MOD will generate all the numbers between and including 0 and MOD-1 when MOD numbers are generated. Otherwise, your program should print the message "Bad Choice". After each output test set, your program should print exactly one blank line.

Sample Input

3 5
15 20
63923 99999

Sample Output

         3         5    Good Choice

        15        20    Bad Choice

     63923     99999    Good Choice

Source


Regionals 1996 >> North America - South Central USA


问题链接HDU1014 POJ1597 UVALive5492 UVA408 ZOJ1314 Uniform Generator

问题简述:(略)

问题分析:这是一个数论题,可以根据题意用暴力法来求解,也可以根据数论原理使用最大公约数来求解。

程序说明:(略)

题记:(略)

 

AC的C语言程序如下

/* HDU1014 POJ1597 UVALive5492 UVA408 ZOJ1314 Uniform Generator */

#include <stdio.h>

int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a % b);
}

int main(void)
{
    int step, mod;

    while (scanf("%d%d", &step, &mod) != EOF)
        printf("%10d%10d    %s\n\n", step, mod, gcd(step, mod) == 1 ? "Good Choice" : "Bad Choice");

    return 0;
}

AC的C语言程序如下

/* HDU1014 POJ1597 UVALive5492 UVA408 ZOJ1314 Uniform Generator */

#include <stdio.h>
#include <string.h>

#define N 100000
int a[N + 1];

int main(void)

{
    int step, mod, i;

    while (scanf("%d%d", &step, &mod) != EOF) {
        memset(a, 0, sizeof(a));

        i = 0;
        while(! a[i]) {
            a[i] = 1;
            i = (i + step) % mod;
        }

        for(i=0; i<mod; i++)
            if(a[i] == 0)
                break;

        printf("%10d%10d    %s\n\n", step, mod, i == mod ? "Good Choice" : "Bad Choice");
    }

    return 0;
}


作者:tigerisland45 发表于2017/11/14 8:12:54 原文链接
阅读:1 评论:0 查看评论

Python基础入门之函数

$
0
0

5.1Python之什么是函数


我们知道圆的面积计算公式为:

S = πr²

当我们知道半径r的值时,就可以根据公式计算出面积。假设我们需要计算3个不同大小的圆的面积:

r1 = 12.34

r2 = 9.08

r3 = 73.1

s1 = 3.14 * r1 * r1

s2 = 3.14 * r2 * r2

s3 = 3.14 * r3 * r3

当代码出现有规律的重复的时候,你就需要当心了,每次写3.14 * x * x不仅很麻烦,而且,如果要把3.14改成3.14159265359的时候,得全部替换。

有了函数,我们就不再每次写s = 3.14 * x * x,而是写成更有意义的函数调用 s = area_of_circle(x),而函数 area_of_circle 本身只需要写一次,就可以多次调用。

抽象是数学中非常常见的概念。举个例子:

计算数列的和,比如:1 + 2 + 3 + ... + 100,写起来十分不方便,于是数学家发明了求和符号∑,可以把1 + 2 + 3 + ... + 100记作:

100

n

n=1

这种抽象记法非常强大,因为我们看到∑就可以理解成求和,而不是还原成低级的加法运算。

而且,这种抽象记法是可扩展的,比如:

100

(n²+1)

n=1

还原成加法运算就变成了:

(1 x 1 + 1) + (2 x 2 + 1) + (3 x 3 + 1) + ... + (100 x 100 + 1)

可见,借助抽象,我们才能不关心底层的具体计算过程,而直接在更高的层次上思考问题。

写计算机程序也是一样,函数就是最基本的一种代码抽象的方式。

Python不但能非常灵活地定义函数,而且本身内置了很多有用的函数,可以直接调用。

任务1

此节没有任务。


5.2Python之调用函数


Python内置了很多有用的函数,我们可以直接调用。

要调用一个函数,需要知道函数名称参数,比如求绝对值的函数 abs,它接收一个参数。

可以直接从Python的官方网站查看文档:

http://docs.python.org/2/library/functions.html#abs

也可以在交互式命令行通过 help(abs) 查看abs函数的帮助信息。

调用 abs 函数:

>>> abs(100)

100

>>> abs(-20)

20

>>> abs(12.34)

12.34

调用函数的时候,如果传入的参数数量不对,会报TypeError的错误,并且Python会明确地告诉你:abs()有且仅有1个参数,但给出了两个:

>>> abs(1, 2)

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

TypeError: abs() takes exactly one argument (2 given)

如果传入的参数数量是对的,但参数类型不能被函数所接受,也会报TypeError的错误,并且给出错误信息:str是错误的参数类型:

>>> abs('a')

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

TypeError: bad operand type for abs(): 'str'

而比较函数 cmp(x, y) 就需要两个参数,如果 x<y,返回 -1,如果 x==y,返回 0,如果 x>y,返回 1

>>> cmp(1, 2)

-1

>>> cmp(2, 1)

1

>>> cmp(3, 3)

0

Python内置的常用函数还包括数据类型转换函数,比如   int()函数可以把其他数据类型转换为整数:

>>> int('123')

123

>>> int(12.34)

12

str()函数把其他类型转换成 str:

>>> str(123)

'123'

>>> str(1.23)

'1.23'

任务2

sum()函数接受一个list作为参数,并返回list所有元素之和。请计算 1*1 + 2*2 + 3*3 + ... + 100*100。


5.3、Python之编写函数


在Python中,定义一个函数要使用 def 语句,依次写出函数名括号、括号中的参数冒号:,然后,在缩进块中编写函数体,函数的返回值用 return 语句返回。

我们以自定义一个求绝对值的 my_abs 函数为例:

def my_abs(x):

    if x >= 0:

        return x

    else:

        return -x

请注意,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。

如果函数中一个return语句都没有,函数执行完毕后也会返回结果,只是结果为 None。如:

def my_abs():

   print 'aaa' 

print my_abs()

输出结果:

aaa

None

如果有一个return语句,那么按照函数内容输出,如:

def myobs(a):

    if a >= 0:

        return a 

myobs(-2)

没有输出值,None也没有

return None可以简写为return。

任务

请定义一个 square_of_sum 函数,它接受一个list,返回list中每个元素平方的和。


任务答案:

任务2:

方法一:

L = []

x = 1

while x <= 100:

    L.append(x * x)

    x = x + 1

print sum(L)


方法二:

L = []

for i in range(1,101):

    L.append(i * i)

print sum(L)


任务3:

def square_of_sum(L):

    sum = 0

    for i in L:

        sum = sum + i * i

    return sum


print square_of_sum([1, 2, 3, 4, 5])

print square_of_sum([-5, 0, 5, 15, 25])







作者:hbblzjy 发表于2017/11/14 9:35:24 原文链接
阅读:0 评论:0 查看评论

Angular 4入门教程系列:15:NG-ZORRO的使用方式

$
0
0

这篇文章介绍一下Angular的优秀国内UI组件库NG-ZORRO,并演示一下如何使引入NG-ZORRO到项目之中。

Why NG-ZORRO

NG-ZORRO由阿里计算平台事业部、阿里云等不同部门的开发人员在原业务组件的基础上构建而成,于2017/8/15在github上发布了第一个对外的版本0.5.0-rc.0,版本更新很快,三个月已经接近有12次更新之多,基本周发布的快速迭代,目前最新版本为0.6.0-rc.3。使用NG-ZORRO有很多原因,比如

  • 组件类型丰富
  • 生态可以结合ant-design
  • 结合阿里在自己项目中的经验
  • 版本更新迭代很快
  • 界面漂亮一些
  • E文不好的开发者的福音
  • ……

NG-ZORRO网址

事前准备

安装node

详细可以参照:http://blog.csdn.net/liumiaocn/article/details/78510679

[root@angular ~]# npm -v
5.5.1
[root@angular ~]# 
[root@angular ~]# node -v
v9.1.0
[root@angular ~]#

安装angular-cli

安装命令:npm install -g @angular/cli –unsafe-perm

[root@angular ~]# npm install -g @angular/cli --unsafe-perm
/usr/local/npm/node/bin/ng -> /usr/local/npm/node/lib/node_modules/@angular/cli/bin/ng

> node-sass@4.6.1 install /usr/local/npm/node/lib/node_modules/@angular/cli/node_modules/node-sass
> node scripts/install.js

Downloading binary from https://github.com/sass/node-sass/releases/download/v4.6.1/linux-x64-59_binding.node
Download complete  ] - :
Binary saved to /usr/local/npm/node/lib/node_modules/@angular/cli/node_modules/node-sass/vendor/linux-x64-59/binding.node
Caching binary to /root/.npm/node-sass/4.6.1/linux-x64-59_binding.node

> node-sass@4.6.1 postinstall /usr/local/npm/node/lib/node_modules/@angular/cli/node_modules/node-sass
> node scripts/build.js

Binary found at /usr/local/npm/node/lib/node_modules/@angular/cli/node_modules/node-sass/vendor/linux-x64-59/binding.node
Testing binary
Binary is fine
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.3 (node_modules/@angular/cli/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ @angular/cli@1.5.0
added 148 packages and updated 1 package in 122.371s
[root@angular ~]#

设定link

[root@angular ~]# ln -s /usr/local/npm/node/lib/node_modules/@angular/cli/bin/ng /usr/local/bin/ng
[root@angular ~]# which ng
/usr/local/bin/ng
[root@angular ~]# ng version

    _                      _                 ____ _     ___
   / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
  / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
 / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
/_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
               |___/

Angular CLI: 1.5.0
Node: 9.1.0
OS: linux x64
Angular: 
...
[root@angular ~]# 

安装typescript

[root@angular ~]# npm install -g typescript
/usr/local/npm/node/bin/tsc -> /usr/local/npm/node/lib/node_modules/typescript/bin/tsc
/usr/local/npm/node/bin/tsserver -> /usr/local/npm/node/lib/node_modules/typescript/bin/tsserver
+ typescript@2.6.1
updated 1 package in 9.327s
[root@angular ~]# 

创建cli项目骨架

[root@angular ~]# ng new NgzorroProject
  create NgzorroProject/README.md (1030 bytes)
  create NgzorroProject/.angular-cli.json (1250 bytes)
  create NgzorroProject/.editorconfig (245 bytes)
  create NgzorroProject/.gitignore (516 bytes)
  create NgzorroProject/src/assets/.gitkeep (0 bytes)
  create NgzorroProject/src/environments/environment.prod.ts (51 bytes)
  create NgzorroProject/src/environments/environment.ts (387 bytes)
  create NgzorroProject/src/favicon.ico (5430 bytes)
  create NgzorroProject/src/index.html (301 bytes)
  create NgzorroProject/src/main.ts (370 bytes)
  create NgzorroProject/src/polyfills.ts (2667 bytes)
  create NgzorroProject/src/styles.css (80 bytes)
  create NgzorroProject/src/test.ts (1085 bytes)
  create NgzorroProject/src/tsconfig.app.json (211 bytes)
  create NgzorroProject/src/tsconfig.spec.json (304 bytes)
  create NgzorroProject/src/typings.d.ts (104 bytes)
  create NgzorroProject/e2e/app.e2e-spec.ts (297 bytes)
  create NgzorroProject/e2e/app.po.ts (208 bytes)
  create NgzorroProject/e2e/tsconfig.e2e.json (235 bytes)
  create NgzorroProject/karma.conf.js (923 bytes)
  create NgzorroProject/package.json (1320 bytes)
  create NgzorroProject/protractor.conf.js (722 bytes)
  create NgzorroProject/tsconfig.json (363 bytes)
  create NgzorroProject/tslint.json (2985 bytes)
  create NgzorroProject/src/app/app.module.ts (316 bytes)
  create NgzorroProject/src/app/app.component.css (0 bytes)
  create NgzorroProject/src/app/app.component.html (1120 bytes)
  create NgzorroProject/src/app/app.component.spec.ts (986 bytes)
  create NgzorroProject/src/app/app.component.ts (207 bytes)
Installing packages for tooling via npm.
Installed packages for tooling via npm.
Project 'NgzorroProject' successfully created.
[root@angular ~]# 

确认结果

[root@angular ~]# cd NgzorroProject/
[root@angular NgzorroProject]# ng serve -H 0.0.0.0 --open
** NG Live Development Server is listening on 0.0.0.0:4200, open your browser on http://localhost:4200/ **
 10% building modules 5/5 modules 0 active(node:2129) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Exited with code 3
(node:2129) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.                   Date: 2017-11-13T21:48:17.734Z            Hash: 90e96d65fc65e5d3a5ba                    
Time: 27952ms
chunk {inline} inline.bundle.js (inline) 5.79 kB [entry] [rendered]
chunk {main} main.bundle.js (main) 20.1 kB [initial] [rendered]
chunk {polyfills} polyfills.bundle.js (polyfills) 547 kB [initial] [rendered]
chunk {styles} styles.bundle.js (styles) 33.4 kB [initial] [rendered]
chunk {vendor} vendor.bundle.js (vendor) 7.02 MB [initial] [rendered]

webpack: Compiled successfully.

这里写图片描述

安装NG-ZORRO

[root@angular NgzorroProject]# npm install ng-zorro-antd --save --unsafe-perm

> node-sass@4.6.1 install /root/NgzorroProject/node_modules/node-sass
> node scripts/install.js

Cached binary found at /root/.npm/node-sass/4.6.1/linux-x64-59_binding.node

> node-sass@4.6.1 postinstall /root/NgzorroProject/node_modules/node-sass
> node scripts/build.js

Binary found at /root/NgzorroProject/node_modules/node-sass/vendor/linux-x64-59/binding.node
Testing binary
Binary is fine
npm WARN codelyzer@3.2.2 requires a peer of @angular/compiler@^2.3.1 || >=4.0.0-beta <5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN codelyzer@3.2.2 requires a peer of @angular/core@^2.3.1 || >=4.0.0-beta <5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN ng-zorro-antd@0.6.0-rc.3 requires a peer of @angular/animations@^4.4.4 but none is installed. You must install peer dependencies yourself.
npm WARN ng-zorro-antd@0.6.0-rc.3 requires a peer of @angular/common@^4.4.4 but none is installed. You must install peer dependencies yourself.
npm WARN ng-zorro-antd@0.6.0-rc.3 requires a peer of @angular/core@^4.4.4 but none is installed. You must install peer dependencies yourself.
npm WARN ng-zorro-antd@0.6.0-rc.3 requires a peer of @angular/forms@^4.4.4 but none is installed. You must install peer dependencies yourself.
npm WARN @angular/cdk@2.0.0-beta.12 requires a peer of @angular/core@~4.4.4 but none is installed. You must install peer dependencies yourself.
npm WARN @angular/cdk@2.0.0-beta.12 requires a peer of @angular/common@~4.4.4 but none is installed. You must install peer dependencies yourself.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.3 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ ng-zorro-antd@0.6.0-rc.3
added 148 packages and updated 1 package in 35.176s
[root@angular NgzorroProject]#

NG-ZORRO设定

代码

修改app.module.ts,将NgZorroAntdModule给import进来,只需要添加两行即可。

[root@angular app]# cat app.module.ts 
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { NgZorroAntdModule } from 'ng-zorro-antd';

import { AppComponent } from './app.component';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    NgZorroAntdModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
[root@angular app]#

特点

  • 根 module 使用 NgZorroAntdModule.forRoot()
  • 子 module 使用 NgZorroAntdModule
  • NgZorroAntdModule.forRoot() 方法可以接受配置文件

修改HTML模板

代码

修改app.component.html

[root@angular app]# cat app.component.html 
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
  <h1>
    Welcome to {{title}}!
  </h1>
</div>
<h2>Buttons</h2>
<button nz-button [nzType]="'primary'">primary</button>
<button nz-button [nzType]="'dashed'">dashed</button>
<button nz-button [nzType]="'default'">default</button>
<button nz-button [nzType]="'danger'">danger</button>
<button nz-button [nzShape]="'default'">defaultShape</button>
<button nz-button [nzShape]="'circle'">O</button>
<button nz-button [nzSize]="'large'">L</button>
<button nz-button [nzSize]="'default'">M</button>
<button nz-button [nzSize]="'small'">S</button>
<button nz-button [nzGhost]="true">L</button>
<button nz-button [nzLoading]="true">L</button>
[root@angular app]# 

特点

  • 组件和指令都是以nz-打头,比如按钮的nz-button
  • 组件和指令的属性都是nz打头其后驼峰命名,比如nzSize
  • 栅格划为24等分

结果确认

这里写图片描述

总结

这篇文章介绍了如何在项目中使用NG-ZORRO,期待国产能够走得更好。

作者:liumiaocn 发表于2017/11/14 5:25:17 原文链接
阅读:29 评论:0 查看评论

前端基础-02-CSS选择器

$
0
0

前端基础-CSS样式

1. CSS样式常用的三种引用方式:

#CSS样式分为3种:
#优先级:行内样式>内嵌样式>外部样式
1.行内样式:
<div style="width: 300px;height: 300px;background: green">
</div>

2.内嵌样式
head中间添加样式:
<style>
        div{
            width: 200px;
            height: 200px;
            background: green;
        }
</style>
3.外部样式
lesson.css样式文件:
div {
    width: 200px;
    height: 200px;
    background: green;
}
#引用方式:
<link rel="stylesheet" href="lesson.css">

扩展:修改页面页签的图标:
<link rel="shortcut icon" href="image/test1.ico">

2.选择器

#1.通配符选择器
* {
    margin: 0;
}

#2.标签(tagName)选择器
div {
   width: 100px;
   height: 100px;
   background: red;
}
#3.class选择器,一般给具有相同属性的元素设置同一个class
.box {
     background: blue;
}
#4.id选择器,id具有唯一性

#box{
     background: gray;
}
#5. +是相邻选择器,操作的对象是该元素后的同级元素,只会针对一个元素
 div + p+p {
    background: blue;
}
#6.群组选择器,对几个相同熟悉的选择器进行样式设置,div和p都生效
        div, p {
            width: 100px;
            height: 100px;
            background: red;
        }
#7. ~ 是兄弟选择器:div后所有同级p元素生效
        div ~ p {
            background: green;
        }
#8.>子代选择器 :div所有子元素p生效,变成蓝色
        div > p {
            background: blue;
        }
#9.后代选择器:可以指定某一层级子元素生效,div的下面所有li元素样式生效
        div li {
            width: 50px;
            height: 50px;
            background: red;
        }
#10.伪选择器
       #a标签:
        a:link { /*未被点击的链接*/
            color: red;
        }

        a:visited { /*已被点击的链接*/
            color: green;
        }

        a:hover { /*鼠标悬浮的颜色*/
            color: aqua;
        }

        a:active { /*鼠标按下的颜色*/
            color: black;
        }

       #div标签:
        div {
            width: 100px;
            height: 100px;
            background: red;
        }

        div:hover { /*改变元素本身*/
            /*
                default 默认箭头
                pointer 手指
                wait 显示正忙
                help 显示帮助
            */
            cursor: pointer;
            background: blue;
        }

        div:hover p { /*改变元素下面的p标签*/
            width: 100px;
            height: 20px;
            background: green;
        }


#11.通用选择器的优先级:
选择器优先级:
(*)<tagName<(.)class类选择器<(#)id选择器
级别相同的选择器,后面的样式会覆盖前面的
复杂后代选择器:
1.先比id 再比class 再比tagName
2.id选择器个数不相等,id越多,优先级越高
3.id选择器相同,则比class,在比tagName

# 快捷键:
ul>li*5   + TABL  快捷输出5个li标签
作者:lianjiaokeji 发表于2017/11/14 9:46:24 原文链接
阅读:1 评论:0 查看评论

数据结构与算法分析(Java语言描述)(16)—— 二叉搜索树基础、节点插入、查找

$
0
0

这里写图片描述

这里写图片描述


基础


// 二叉搜索树
// 由于Key需要能够进行比较,所以需要extends Comparable<Key>
public class BinarySearchTree<Key extends Comparable<Key>, Value> {

    // 树中的节点为私有的类,外界不需要了解二叉搜索树节点的具体实现
    private class Node{
        private Key key;
        private Value value;
        private Node left, right;

        Node(Key key, Value value){
            this.key = key;
            this.value = value;
            this.left = null;
            this.right = null;
        }
    }

    private Node root; // 根节点
    private int count; // 树中的节点个数

    // 构造函数,默认构造一棵空二叉搜索树
    public BinarySearchTree() {
        root = null;
        count = 0;
    }

    // 返回二叉搜索树的节点个数
    public int size() {
        return count;
    }

    // 返回二叉搜索树是否为空
    public boolean isEmpty() {
        return count == 0;
    }
}

节点插入


    // 向二叉搜索树中插入一个新的(key,value)数据对
    public void insert(Key key, Value value) {
        root = insert(root, key, value);
    }

    // 向以 node 为根的二叉搜索树中插入新节点(key,value),使用递归算法
    private Node insert(Node node, Key key, Value value) {
        // 递归到底的情况
        if (node == null) {
            count++;
            return new Node(key, value);
        }

        // 如果要插入的 key == node.key,更新 node.value
        if (key.compareTo(node.key) == 0) {
            node.value = value;

            // 如果要插入的 key > node.key,向右子树 insert
        } else if (key.compareTo(node.key) > 0) {
            node.right = insert(node.right, key, value);

            // 如果要插入的 key < node.key,向左子树 insert
        } else {
            node.left = insert(node.left, key, value);
        }

        // 返回 insert (key,value) 后 二叉搜索树的根节点
        return node;
    }

查找


    // 查看二叉搜索树中是否包含 key
    public boolean contain(Key key) {
        return contain(root, key);
    }

    // 查看以 node 为根的二叉搜索树中是否包含键值为 key 的节点,使用递归算法
    private boolean contain(Node node, Key key) {
        // 递归到底
        if (node == null) {
            return false;
        }

        if (key.compareTo(node.key) == 0) {
            return true;
        } else if (key.compareTo(node.key) > 0) {
            return contain(node.right, key);
        } else { // key < node->key
            return contain(node.left, key);
        }
    }
    // 在二叉搜索树中搜索键key所对应的值。如果这个 key 不存在, 则返回null
    public Value search(Key key) {
        return search(root, key);
    }

    // 在以 node 为根的二叉搜索树中搜索 key 所对应的 value,递归算法
    private Value search(Node node, Key key) {
        // 递归到底,二叉搜索树中不存在键值 key ,返回 null
        if (node == null) {
            return null;
        }
        if (key.compareTo(node.key) == 0) {
            return node.value;
        } else if (key.compareTo(node.key) > 0) {
            return search(node.right, key);
        } else { // key < node.key
            return search(node.left, key);
        }
    }  
作者:HeatDeath 发表于2017/11/14 10:37:46 原文链接
阅读:0 评论:0 查看评论

LeetCode-152:Maximum Product Subarray (乘积最大连续子数组) -- medium

$
0
0

Question

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

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

问题解析:

给定数组,给出最大乘积的连续子数组。

Answer

Solution 1:

DP。

  • 子数组问题很适合使用动态规划来求解,与和最大的连续子数组的思想是相同的。
  • 动态规划问题最核心的思想是找到其状态转移方程。首先说明“和最大的连续子数组”:我们定义,Fi表示以i结尾的和最大的连续子数组,求F0,..,Fn1的最大值。所以这里我们最主要的是处理数组的局部当前最大连续乘积,和全局最大连续乘积的关系。
  • 转换为式子有:
    Fi=Max(Fi1+Ai,Ai);global=Max(Fi,global);
  • 与最大和连续子数组相似,最大乘积连续子数组具有相同的思想,只是需要考虑负数的情况,因为两个负数相乘时,最后得到正值。所以一方面我们在保存乘积最大的值的同时,也要保存最小值(乘负数就是最小),然后比较最小值乘当前值、最大值乘当前值、当前值三者之间的最大和最小值,最大值和全局值比较。
  • 转换为式子有:
    maxFi=Max(maxFi1Ai,Ai,minFi1Ai);minFi=Min(minFi1Ai,Ai,maxFi1Ai);global=Max(maxFi,global);
class Solution {
    public int maxProduct(int[] nums) {
        if (nums == null || nums.length == 0) return 0;
        if (nums.length == 1) return nums[0];

        int[] maxhere = new int[nums.length];
        int[] minhere = new int[nums.length];
        maxhere[0] = nums[0];
        minhere[0] = nums[0];
        int res = nums[0];

        for (int i = 1; i < nums.length; i++){
            maxhere[i] = Math.max(Math.max(maxhere[i-1]*nums[i], nums[i]), minhere[i-1]*nums[i]);
            minhere[i] = Math.min(Math.min(minhere[i-1]*nums[i], nums[i]), maxhere[i-1]*nums[i]);
            res = Math.max(res, maxhere[i]);
        }

        return res;
    }
}
  • 时间复杂度:O(n),空间复杂度:O(n)

Solution 2:

对Solution1的DP优化。

  • 通过观察状态转移函数,我们可以看出,每次计算只是用到前一个maxhereminhere,所以这里可以对程序进行改进,每次对前一个maxhereminhere做记录,这样就节省了空间的存储。
  • 因为在我们的程序中,先计算maxhere,后计算minhere,所以只有在计算minhere时,当前的maxhere[i]会覆盖之前的maxhere[i-1],所以我们在每次计算前,将前一个minhere保存下来,以便后面计算使用。
class Solution {
    public int maxProduct(int[] nums) {
        if (nums == null || nums.length == 0) return 0;
        if (nums.length == 1) return nums[0];

        int maxhere = nums[0];
        int minhere = nums[0];
        int res = nums[0];

        for (int i = 1; i < nums.length; i++){
            int maxpre = maxhere;
            maxhere = Math.max(Math.max(maxpre*nums[i], nums[i]), minhere*nums[i]);
            minhere = Math.min(Math.min(minhere*nums[i], nums[i]), maxpre*nums[i]);
            res = Math.max(res, maxhere);
        }

        return res;
    }
}
  • 时间复杂度:O(n),空间复杂度:O(1)
作者:Koala_Tree 发表于2017/11/14 10:43:14 原文链接
阅读:0 评论:0 查看评论

数据结构与算法分析(Java语言描述)(17)—— 二叉搜索树的深度优先与广度优先遍历

$
0
0

二叉搜索树的深度优先遍历


这里写图片描述

先序遍历


这里写图片描述

// 先序遍历二叉搜索树
    public void preOrder() {
        preOrder(root);
    }

    // 对以node为根的二叉搜索树进行前序遍历, 递归算法
    private void preOrder(Node node) {
        if (node != null) {
            System.out.println(node.value);
            preOrder(node.left);
            preOrder(node.right);
        }
    }

中序遍历


这里写图片描述

// 中序遍历二叉搜索树
    public void inOrder(){
        inOrder(root);
    }

    // 对以 node 为根的二叉搜索树进行中序遍历,递归算法
    private void inOrder(Node node){
        if (node != null){
            inOrder(node.left);
            System.out.println(node.value);
            inOrder(node.right);
        }
    }

后序遍历


这里写图片描述

// 后序遍历二叉搜索树
    public void postOrder(){
        postOrder(root);
    }

    // 对以 node 为根的二叉搜索树进行后序遍历,递归算法
    private void postOrder(Node node){
        if (node != null){
            postOrder(node.left);
            postOrder(node.right);
            System.out.println(node.value);
        }
    }

二叉树的广度优先遍历


这里写图片描述

层序遍历


// 二叉搜索树的层序遍历(广度优先)
    public void levelOrder(){
        // 使用LinkedList来作为我们的队列
        LinkedList<Node> q = new LinkedList<>();
        q.add(root);

        // 先将 根节点 放入 q 中,再移除 此节点,将此节点的 左子节点 和 右子节点 放入 q 中
        // 直到 q 为空
        while (!q.isEmpty()) {
            Node node = q.remove();
            System.out.println(node.key);

            if (node.left != null) q.add(node.left);
            if (node.right != null) q.add(node.right);
        }
    }

作者:HeatDeath 发表于2017/11/14 10:43:16 原文链接
阅读:0 评论:0 查看评论

LeetCode--Validate Binary Search Tree

$
0
0

Given a binary tree, determine if it is a valid binary search tree (BST).

Assume a BST is defined as follows:

The left subtree of a node contains only nodes with keys less than the node’s key.
The right subtree of a node contains only nodes with keys greater than the node’s key.
Both the left and right subtrees must also be binary search trees.
Example 1:

    2
   / \
  1   3

Binary tree [2,1,3], return true.
Example 2:

    1
   / \
  2   3

Binary tree [1,2,3], return false.

思路:中序遍历。将二叉树中序遍历后存放到数组中,判断数组是升序的,就是二叉搜索树。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode* root) {
        if(!root) return true;
        vector<int>vals;
        inorder(root,vals);
        for(int i=0;i<vals.size()-1;i++){
            if(vals[i]>=vals[i+1]) return false;
        }
        return true;
    }
    void inorder(TreeNode* root,vector<int>&vals){
        if(root){
            inorder(root->left,vals);
            vals.push_back(root->val);
            inorder(root->right,vals);
        }
    }
};
作者:qq_20791919 发表于2017/11/14 10:43:58 原文链接
阅读:0 评论:0 查看评论

Android单元测试:测试RxJava的同步及异步操作

$
0
0

简述

在您开发的项目中,您使用了RxJava+Retrofit的网络请求框架,在RxJava强大的操作符下,您理所当然的认为您已经能够游刃有余地处理Android客户端开发中的联网请求需求,比如这样:

//Model层的网络请求
public class HomeModel extends BaseModel<ServiceManager> implements HomeContract.Model {

 @Override
 public Maybe<UserInfo> requestUserInfo(final String userName) {
      return serviceManager.getUserInfoService()
              .getUserInfo(userName)
              .subscribeOn(Schedulers.io())
              .observeOn(AndroidSchedulers.mainThread());
  }
}

//Presenter层的网络处理
public class HomePresenter extends BasePresenter<HomeContract.View, HomeContract.Model> implements HomeContract.Presenter {

    @Inject
    public HomePresenter(HomeContract.View rootView, HomeContract.Model model) {
        super(rootView, model);
    }

    @SuppressLint("VisibleForTests")
    @Override
    public void requestUserInfo(String userName) {
        mModel.requestUserInfo(userName)
                .subscribe(info -> Optional.ofNullable(info)
                                .map(UserInfo::getLogin)
                                .ifPresentOrElse(image -> mRootView.onGetUserInfo(info)
                                        , () -> mRootView.onError("用户信息为空"))
                        , e -> mRootView.onError("请求出现异常"));
    }
}

这是一个非常简单的MVP开发模式下的一个联网请求代码,用于请求用户的信息数据,我们不需要强制性理解每一行代码,我们需要关注的问题是,我们如何保证这些代码的正确性,即使在一些边界条件的限制下?

单元测试能够让项目中自己的代码更加健壮,但是无论是RxJava+Retrofit,亦或是okHttp3,异步操作的测试都是一个较高的门槛,加上目前国内开发环境的恶劣环境(周期短,需求变动反复),国内的相关技术文档相当匮乏。

Espresso的异步测试

笔者曾经花费一些时间研究Espresso的异步测试,并根据google官方的demo尝试总结在设备上进行测试异步操作的方案:

Android 自动化测试 Espresso篇:异步代码测试

这是可行的,但是有一些问题需要注意:

1.Espresso本质是依赖设备所进行的集成测试,这种测试是业务级的,测试的内容是一个整体的功能,相对于代码(方法)级别的单元测试,覆盖范围太大。
2.Espresso的测试依赖设备,所以进行一次完整的测试所消耗的时间更长。
3.Espresso更擅长UI的测试,而对于业务代码来说,Espresso并不擅长。

现在我们需要一种新的方式去测试业务代码,比如Junit+Mockito.

异步测试的难题

在尝试RxJava的单元测试时,不可避免的,你会遇到两个问题:

1.如何测试异步代码?
2.如何测试AndroidSchedulers.mainThread()?

1.异步操作如何转为同步进行单元测试?

前者的问题我们已经在之前的Android 自动化测试 Espresso篇:异步代码测试这篇文章中提到过了,那就是:

在我们还没有获取到数据进行验证时,测试代码已经跑完了。

以下面一段代码为例:

//开启一个子线程,每隔一秒发送一个数据,共发射10次,结果输出 0~9
@Test
fun test() {
Observable.intervalRange(0, 10, 0, 1, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(i -> System.out.println(i))
}

理所当然的认为,我们能看到输出台上输出0~9,事实上,数据还没有输出一个,测试代码就已经跑完了,所以结果是,输出台空空如也。

单纯的使用Thread.sleep(10000)使当前的线程停留10秒不一定是最简单,但一定是最差的选择,因为这意味着我们需要花费更长时间去等待测试结果,更重要的问题是,并非每次我们都能直到异步操作的所需要的准确时间。

RxJavaPlugins

很快我找到了这篇文章:

Rxjava2单元测试的异步和同步转换

这篇文章是为数不多对我测试RxJava有用的文章之一,作者使用RxJavaPlugins,通过将RxJava所使用的线程换成Schedulers.trampoline()的方式,强制立即进行当前的任务,从而得到单元测试的结果。

代码如下:

    /**
     * 单元测试的时候,利用RxJavaPlugins将io线程转换为trampoline
     * trampoline应该是立即执行的意思(待商榷),替代了Rx1的immediate。
     */
    public static void asyncToSync() {
        RxJavaPlugins.reset();
        RxJavaPlugins.setIoSchedulerHandler(new Function<Scheduler, Scheduler>() {
            @Override
            public Scheduler apply(Scheduler scheduler) throws Exception {
                return Schedulers.trampoline();
            }
        });

然后再在测试类里加这么一句:

@Before
 public void setUp(){
     //将rx异步转同步
     RxjavaFactory.asyncToSync();
 } 

令我振奋的是,我成功得到了预期的结果。

TestScheduler

我们通过上面的代码,解决了一大部分的异步测试需求,但是还有一个问题,那就是测试的时间,我们不希望这个测试花费这么长时间。

RxJava2的开发人员已经为我们考虑到了这个问题,对此他们提供了TestScheduler类,很明显,这也是一个Scheduler.

我们定义一个Rule,用来配置TestScheduler代替我们所使用的其他Scheduler,这是一个特殊的scheduler,它允许我们手动的将一个虚拟时间提前:

class RxSchedulerRule : TestRule {

    private var testScheduler: TestScheduler = TestScheduler()

    override fun apply(base: Statement?, description: Description?): Statement {
        return object : Statement() {
            @Throws(Throwable::class)
            override fun evaluate() {
                RxJavaPlugins.setIoSchedulerHandler { testScheduler }
                RxJavaPlugins.setComputationSchedulerHandler { testScheduler }
                RxJavaPlugins.setNewThreadSchedulerHandler { testScheduler }
                RxJavaPlugins.setSingleSchedulerHandler { testScheduler }
//                RxAndroidPlugins.setInitMainThreadSchedulerHandler { testScheduler }
                try {
                    base?.evaluate()
                } finally {
                    RxJavaPlugins.reset()
//                    RxAndroidPlugins.reset()
                }
            }
        }
    }

    //advanceTimeTo()以绝对的方式调整时间
    fun advanceTimeTo(delayTime: Long, timeUnit: TimeUnit) {
        testScheduler.advanceTimeTo(delayTime, timeUnit)
    }

    //advanceTimeBy()方法将调度器的时间调整为相对于当前位置的时间
    fun advanceTimeBy(delayTime: Long, timeUnit: TimeUnit) {
        testScheduler.advanceTimeBy(delayTime, timeUnit)
    }

    fun getScheduler(): TestScheduler {
        return testScheduler
    }
}

对此,我们在每个测试类中添加这个Rule即可:

 @Rule
 @JvmField
 val rxRule = RxSchedulerRule()

在Kotlin的测试代码中,我们需要添加@JvmField注释,因为@Rule注释仅适用于字段和getter方法,但rxRule 是Kotlin中的一个属性。

现在 我们再次进行测试:

class RxSchedulerRule_Test {

    @Rule
    @JvmField
    val rxRule = RxSchedulerRule()

    @Test
    fun testAdvanceTo_complete() {
        val observer = startRangeLoopThread()

        //将时间轴跳到第10秒,模拟执行发生的事件
        rxRule.advanceTimeTo(10, TimeUnit.SECONDS)

        assertComplete(observer)
    }

    private fun startRangeLoopThread(): TestObserver<Long> {
        val observer = TestObserver<Long>()
        val observable = getThread()
        observable.subscribe(observer)
        return observer
    }

    //开启一个子线程,每隔一秒发送一个数据,共发射10次,结果 0~9
    private fun getThread(): Observable<Long> {
        return Observable.intervalRange(0, 10, 0, 1, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.newThread())
    }

    //断言
    private fun assertComplete(observer: TestObserver<Long>) {
        observer.assertValueCount(10)
                .assertComplete()
                .assertNoErrors()
                .assertValueAt(0, 0)
                .assertValueAt(9, 9)
    }
}

这样我们仅仅需要数十或者数百毫秒,就能准确测试这个异步操作,并且验证我们预期的结果。

如何测试AndroidSchedulers.mainThread()

单纯的直接测试会导致报错:找不到AndroidSchedulers这个类。

我们将RxSchedulerRule 中的两行注解代码打开,这意味着当我们要使用AndroidSchedulers这个类时,RxAndroidPlugins已经用TestScheduler替换了AndroidSchedulers.mainThread()。

这样就解决了这个问题。

但是我很快遇到了一个奇怪的现象,那就是

当我一次运行整个测试类时,只有第一个测试通过,其余的测试通常会失败。

这个现象困扰我很久,最终我找到的解决方式是,通过依赖注入解决问题:

参考 【译】使用Kotlin和RxJava测试MVP架构的完整示例 - 第2部分 @ditclear

首先要做到这一点,我们需要创建一个SchedulerProvider接口,并提供两个实现。

  • AppSchedulerProvider - 这将为我们提供真正的调度器。 我们将把这个类注入所有的presenter,这将为我们的Rx订阅提供调度器。
  • TestSchedulerProvide - 这个类将为我们提供一个TestScheduler而不是真正的scheduler。 当我们在测试中实例化我们的presenter时,我们将使用它作为它的构造函数参数。
interface SchedulerProvider {
    fun uiScheduler() : Scheduler
    fun ioScheduler() : Scheduler
}

class AppSchedulerProvider : SchedulerProvider {
    override fun ioScheduler() = Schedulers.io()
    override fun uiScheduler(): Scheduler = AndroidSchedulers.mainThread()
}

class TestSchedulerProvider() : SchedulerProvider {

    val testScheduler: TestScheduler = TestScheduler()

    override fun uiScheduler() = testScheduler
    override fun ioScheduler() = testScheduler
}

通过依赖注入,在生产代码中使用AppSchedulerProvider ,在测试代码中使用TestSchedulerProvider。

以最初的MVP中的model和Presenter为例,测试代码如下:

  • Model
class HomeModelTest : BaseTestModel() {

    private var retrofit: MockRetrofit = MockRetrofit()

    private var homeModel: HomeModel = HomeModel(mock())

    val provider = TestSchedulerProvider()

    @Before
    fun setUp() {
        homeModel.schedulers = provider
        homeModel = spy(homeModel)

        val service = retrofit.create(UserInfoService::class.java)
        whenever(homeModel.serviceManager.userInfoService).thenReturn(service)
    }

    @Test
    fun requestUserInfo() {
        val testObserver = TestObserver<UserInfo>()
        retrofit.path = MockAssest.USER_DATA
        doReturn(RxTestTransformer<UserInfo>()).whenever(homeModel).getUserInfoCache(anyString(), anyBoolean())

        val maybe = homeModel.requestUserInfo("qingmei2")
        maybe.subscribe(testObserver)

        provider.testScheduler.triggerActions()

        testObserver.assertValue { it -> it.login == "login" && it.name == "name" }
    }
}
  • Presenter
class HomePresenterTest : BaseTestPresenter() {

    val view: HomeContract.View = mock()

    val model: HomeContract.Model = mock()

    var presenter: HomePresenter = HomePresenter(view, model)

    @Before
    fun setUp() {
        presenter = spy(presenter)
        doReturn(RxTestTransformer<Any>()).whenever(presenter).bindViewMaybe<Any>(view)
    }

    @Test
    fun requestUserInfo_success() {

        val s = MockAssest.readFile(MockAssest.USER_DATA)
        val user = Gson().fromJson(s, UserInfo::class.java)
        whenever(model.requestUserInfo(anyString())).thenReturn(Maybe.just(user))

        //testing
        presenter.requestUserInfo("qingmei2")

        val captor: ArgumentCaptor<UserInfo> = ArgumentCaptor.forClass(UserInfo::class.java)
        verify(view).onGetUserInfo(captor.capture());
        verify(view, never()).onError(anyString());

        assert(user.equals(captor.value))
    }

    @Test
    fun requestUserInfo_failed_error() {
        val s = MockAssest.readFile(MockAssest.error)
        val user = Gson().fromJson(s, UserInfo::class.java)
        whenever(model.requestUserInfo(anyString())).thenReturn(Maybe.just(user))

        presenter.requestUserInfo("qingmei2")

        verify(view, never()).onGetUserInfo(any());
        verify(view).onError("用户信息为空");
    }
}

小结

文笔所限,只是把思路整理一遍写了出来,很多类都没有详细去讲解,比如TestScheduler,比如TestObserver,这都是RxJava提供好的工具,我们一定要好好利用。

虽然思路有些天马行空,但是笔者最近数日整理出来的一套Kotlin的RxJava2+Retrofit的单元测试脚手架已经搭建完毕,并且作为笔者个人MVP架构下的测试框架,配以详细的单元测试代码,上传到了Github上,有需要的朋友可以参考:

MvpArchitecture-Android

参考文章

测试RxJava2
http://www.infoq.com/cn/articles/Testing-RxJava2

【译】使用Kotlin和RxJava测试MVP架构的完整示例 - 第2部分:
http://www.jianshu.com/p/0a845ae2ca64

作者:mq2553299 发表于2017/11/13 22:18:05 原文链接
阅读:15 评论:0 查看评论

TensorFlow MNIST 手写数字识别之过拟合

$
0
0

1. 过拟合 overfitting 问题

什么是过拟合呢?

用实际生活中的一个例子来比喻一下过拟合现象. 说白了, 就是机器学习模型于自信. 已经到了自负的阶段了. 那自负的坏处, 大家也知道, 就是在自己的小圈子里表现非凡, 不过在现实的大圈子里却往往处处碰壁. 所以在这个简介里, 我们把自负和过拟合画上等号.

学习模型可能太满足了所有的训练数据,所以导致在实际数据中误差陡增,如下图,绿的的线是过拟合的训练结果,黑色的分界线是我门期望的结果。

这里写图片描述

解决过拟合

  • 方法一: 增加数据量, 大部分过拟合产生的原因是因为数据量太少了. 如果我们有成千上万的数据, 红线也会慢慢被拉直, 变得没那么扭曲 .

  • 方法二:运用正规化. L1, l2 regularization等等, 这些方法适用于大多数的机器学习, 包括神经网络. 他们的做法大同小异, 我们简化机器学习的关键公式为 y=Wx . W为机器需要学习到的各种参数. 在过拟合中, W 的值往往变化得特别大或特别小. 为了不让W变化太大, 我们在计算误差上做些手脚. 原始的 cost 误差是这样计算, cost = 预测值-真实值的平方. 如果 W 变得太大, 我们就让 cost 也跟着变大, 变成一种惩罚机制. 所以我们把 W 自己考虑进来. 这里 abs 是绝对值. 这一种形式的 正规化, 叫做 l1 正规化. L2 正规化和 l1 类似, 只是绝对值换成了平方. 其他的l3, l4 也都是换成了立方和4次方等等. 形式类似. 用这些方法,我们就能保证让学出来的线条不会过于扭曲.

  • dropout: 在训练的时候, 我们随机忽略掉一些神经元和神经联结 , 是这个神经网络变得”不完整”. 用一个不完整的神经网络训练一次.

    到第二次再随机忽略另一些, 变成另一个不完整的神经网络. 有了这些随机 drop 掉的规则, 我们可以想象其实每次训练的时候, 我们都让每一次预测结果都不会依赖于其中某部分特定的神经元.

2. 在MNIST中解决过拟合

关于处理数据和构建神经网络 请参照博客 TensorFlow 入门之第一个神经网络和训练 MNIST

代码使用了tensorboard 可视化(关于tensorboard 有时间会专门介绍)来观察 loss 函数的变化,使用 dropout来解决过拟合问题。

下面是主要代码

# -*- coding: utf-8 -*-
# 用 drop out 解决 Overfitting 问题
import 手写数字识别.input_data  
import tensorflow as tf
mnist = 手写数字识别.input_data.read_data_sets("手写数字识别/MNIST_data/", one_hot=True)  

# 添加神经层的函数def add_layer(),它有四个参数:输入值、输入的大小、输出的大小和激励函数,我们设定默认的激励函数是None。也就是线性函数
def add_layer(inputs, in_size, out_size,layer_name, activation_function=None):
    # 定义权重,尽量是一个随机变量
    # 因为在生成初始参数时,随机变量(normal distribution) 会比全部为0要好很多,所以我们这里的weights 是一个 in_size行, out_size列的随机变量矩阵。   
    Weights = tf.Variable(tf.random_normal([in_size, out_size]))
    # 在机器学习中,biases的推荐值不为0,所以我们这里是在0向量的基础上又加了0.1。
    biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
    # 定义Wx_plus_b, 即神经网络未激活的值(预测的值)。其中,tf.matmul()是矩阵的乘法。
    Wx_plus_b = tf.matmul(inputs, Weights) + biases
    #  用dropout来解决过拟合 问题
    Wx_plus_b = tf.nn.dropout(Wx_plus_b, keep_prob)
    # activation_function ——激励函数(激励函数是非线性方程)为None时(线性关系),输出就是当前的预测值——Wx_plus_b,
    # 不为None时,就把Wx_plus_b传到activation_function()函数中得到输出。
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        # 返回输出
        outputs = activation_function(Wx_plus_b)
        tf.summary.histogram(layer_name + '/outputs', outputs)
    return outputs

# 保留数据 keep_prob
keep_prob = tf.placeholder(tf.float32)
xs = tf.placeholder(tf.float32,[None, 784]) #图像输入向量  每个图片有784 (28 *28) 个像素点
ys = tf.placeholder(tf.float32, [None,10]) #每个例子有10 个输出

# prediction = add_layer(xs, 784, 10, activation_function=tf.nn.softmax)
l1 = add_layer(xs, 784, 50, 'l1', activation_function=tf.nn.tanh)
prediction = add_layer(l1, 50, 10,'l2' ,activation_function=tf.nn.softmax)
#loss函数(即最优化目标函数)选用交叉熵函数。交叉熵用来衡量预测值和真实值的相似程度,如果完全相同,它们的交叉熵等于零 ,所以loss 越小 学的好
#分类一般都是 softmax+ cross_entropy
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction),
reduction_indices=[1]))
tf.summary.scalar('loss', cross_entropy)

#train方法(最优化算法)采用梯度下降法。  优化器 如何让机器学习提升它的准确率。 tf.train.GradientDescentOptimizer()中的值(学习的效率)通常都小于1
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
sess = tf.Session()

merged = tf.summary.merge_all() # tensorflow >= 0.12
train_writer = tf.summary.FileWriter("/Users/yangyibo/test/logs/train",sess.graph)
test_writer = tf.summary.FileWriter("/Users/yangyibo/test/logs/test",sess.graph)

# 初始化变量
init= tf.global_variables_initializer()
sess.run(init)

for i in range(1000):
    #开始train,每次只取100张图片,免得数据太多训练太慢
    batch_xs, batch_ys = mnist.train.next_batch(50)
    # 丢弃百分之40 的数据
    sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys, keep_prob: 0.5})
    if i % 50 == 0:
        train_result = sess.run(merged, feed_dict={xs: batch_xs, ys: batch_ys, keep_prob: 1})
        test_result = sess.run(merged, feed_dict={xs: mnist.test.images, ys: mnist.test.labels, keep_prob: 1})
        train_writer.add_summary(train_result,i)
        test_writer.add_summary(test_result,i)

本文源码:https://github.com/527515025/pythonLean/blob/master/AI/tensorflow_10_dropout.py

本文参考:莫烦老师的pyhon课程

作者:u012373815 发表于2017/11/13 22:23:49 原文链接
阅读:150 评论:0 查看评论

如何让textarea中输入多行的数据在p标签中换行?

$
0
0

我们在用React开发Web项目的过程中,有的时候,我们需要把textarea中输入的多行字符串,在其他的标签中输出来,比如p标签。但是,往往这个时候,在p标签中输出的内容其默认情况下是不换行的。比如下面的代码:

import React,{Component} from 'react';
export default class HelloWorld extends Component{

  constructor(){
    super(...arguments);
    this.state={
      note:"",
    }
  }

  render(){
    return(
    <div className="app" style={{padding:"10px 5px 15px 20px"}}>
          <form id="noter-save-form" method="POST" style={{topPadding:"100px",leftPadding:"100px"}}>
              <textarea id="noter-text-area" style={{height:"100px"}} name="textarea" onChange={(e)=> this.setState({note:e.target.value}) } ></textarea>
              <hr/>
              <label>The input value for Note:</label>
              <hr/>
              <p>{this.state.note}</p>
              <hr/>
           </form>
    </div>
  );
  }
}

下面是其渲染的结果:
这里写图片描述

我们可以看出,其在TextArea中输入的回车换行,在p标签中,压根显示不出来。
那么这个时候,我们应该怎么办?其实解决的方案很简单,代码入下:

import React,{Component} from 'react';
export default class HelloWorld extends Component{

  constructor(){
    super(...arguments);
    this.state={
      note:"",
    }
  }

  render(){
    return(
    <div className="app" style={{padding:"10px 5px 15px 20px"}}>
          <form id="noter-save-form" method="POST" style={{topPadding:"100px",leftPadding:"100px"}}>
              <textarea id="noter-text-area" style={{height:"100px"}} name="textarea" onChange={(e)=> this.setState({note:e.target.value}) } ></textarea>
              <hr/>
              <label>The input value for Note:</label>
              <hr/>
              <p>
              {this.state.note.split('\n').map(function(item) {
                  return (
                    <span>
                      {item}
                      <br/>
                    </span>
                  )
                })} </p>
              <hr/>
           </form>
    </div>
  );
  }
}

从上面的代码可以看出,我们在p标签中渲染的时候,把textarea中输入的\n
换成了br标签。

 {this.state.note.split('\n').map(function(item) {
                  return (
                    <span>
                      {item}
                      <br/>
                    </span>
                  )
                })} 

换完后,UI渲染的效果如下:
这里写图片描述

作者:chancein007 发表于2017/11/13 23:32:28 原文链接
阅读:150 评论:0 查看评论

leetcode题解-459. Repeated Substring Pattern && 443. String Compression && 434. Number of Segments in

$
0
0

459,Repeated Substring Pattern题目:

Given a non-empty string check if it can be constructed by taking a substring of it and appending multiple copies of the substring together. You may assume the given string consists of lowercase English letters only and its length will not exceed 10000.

Example 1:
Input: "abab"

Output: True

Explanation: It's the substring "ab" twice.
Example 2:
Input: "aba"

Output: False
Example 3:
Input: "abcabcabcabc"

Output: True

Explanation: It's the substring "abc" four times. (And the substring "abcabc" twice.)

这道题感觉跟昨天的686. Repeated String Match挺像的,不过改成了判断一个字符串是否可以有自身的一个子串重复构造而成,很简单,一个最基本的要求就是字符串本身的长度应该是子串长度的整数倍,有了这个我们就可以写出下面这段简单高效的代码:

    //80%,可以击败80%的用户
    public static boolean repeatedSubstringPattern(String s) {

        int len = s.length();
        //i表示将s等分成i份,并且从小到大遍历,这样子字符串从长到短,可以节省判断次数
        for(int i=2; i<=len; i++){
            //必须整除才可以
            if(len%i == 0){
                int count = len / i, j;
                //遍历分成的几份子串是否完全相等,相等即表明可分
                for(j=0; j<i-1; j++){
                    if(!s.substring(j*count, (j+1)*count).equals(s.substring((j+1)*count, (j+2)*count)))
                        break;
                }
                if(j == i-1)
                    return true;
            }
        }
        return false;
    }

除了这种思路,我们还可以使用正则表达式以及一个很巧妙的想法,就是把S直接本身拼接,然后判断拼接后的字符串从1开始的子串T是否包含S,因为如果S可以由一个子串拼接而成,那么新构造的子串T一定是包含S的,我本来以为这种方法效率会很高,但是发现只能击败37%的用户,可能是因为contains函数比较耗时吧。代码如下所示:

    //37%
    public boolean repeatedSubstringPattern2(String str) {
        String s = str + str;
        return s.substring(1, s.length() - 1).contains(str);
    }

    //14%
    public boolean repeatedSubstringPattern1(String str) {
        if(str == null || str.length() < 2) return false;

        boolean result = false;
        for(int i = 1; i <= str.length()/2; i++) {
            if(str.length()%i != 0) continue;
            String regex = "("+str.substring(0,i)+")" + "+";
            result = result | str.matches(regex);
        }
        return result;
    }

最后还有一种高效的解法,使用KMP算法来求解,可以击败88%的用户,至于KMP算法后面应该会专门写一篇博客来介绍,就不在这里多说,直接看代码:

    //88%
    public boolean repeatedSubstringPattern3(String str) {
        //This is the kmp issue
        int[] prefix = kmp(str);
        int len = prefix[str.length()-1];
        int n = str.length();
        return (len > 0 && n%(n-len) == 0);
    }

    private int[] kmp(String s){
        int len = s.length();
        int[] res = new int[len];
        char[] ch = s.toCharArray();
        int i = 0, j = 1;
        res[0] = 0;
        while(i < ch.length && j < ch.length){
            if(ch[j] == ch[i]){
                res[j] = i+1;
                i++;
                j++;
            }else{
                if(i == 0){
                    res[j] = 0;
                    j++;
                }else{
                    i = res[i-1];
                }
            }
        }
        return res;
    }

接下来看443题目:

Given an array of characters, compress it in-place.

The length after compression must always be smaller than or equal to the original array.

Every element of the array should be a character (not int) of length 1.

After you are done modifying the input array in-place, return the new length of the array.


Follow up:
Could you solve it using only O(1) extra space?


Example 1:
Input:
["a","a","b","b","c","c","c"]

Output:
Return 6, and the first 6 characters of the input array should be: ["a","2","b","2","c","3"]

Explanation:
"aa" is replaced by "a2". "bb" is replaced by "b2". "ccc" is replaced by "c3".
Example 2:
Input:
["a"]

Output:
Return 1, and the first 1 characters of the input array should be: ["a"]

Explanation:
Nothing is replaced.
Example 3:
Input:
["a","b","b","b","b","b","b","b","b","b","b","b","b"]

Output:
Return 4, and the first 4 characters of the input array should be: ["a","b","1","2"].

Explanation:
Since the character "a" does not repeat, it is not compressed. "bbbbbbbbbbbb" is replaced by "b12".
Notice each digit has it's own entry in the array.
Note:
All characters have an ASCII value in [35, 126].
1 <= len(chars) <= 1000.

这道题跟昨天的38. Count and Say很像,就是一个统计连续字符长度,然后使用数字表示的题目。接发也非常简单,就不多说了:

    //46%
    public static int compress(char[] chars) {
        if(chars == null || chars.length <= 0)
            return 0;

        char var = chars[0];
        int left=0, right=0;
        for(int i=0; i<chars.length;){
            right = i;
            //统计相同字符连续出现次数
            while(right<chars.length && chars[right] == var) right ++;
            int len = right - i;
            //先写入字符
            chars[left++] = var;
            //如果长度不为1,在将出现次数以char型写入
            if(len != 1) {
                char[] tmp = String.valueOf(len).toCharArray();
                for(char num : tmp)
                    chars[left++] = num;
            }
            //遍历到最后一个元素结束循环
            if (right >= chars.length)
                break;
            i = right;
            var = chars[right];
        }
        return left;
    }

最后我们来看一下434. Number of Segments in a String的题目:

Count the number of segments in a string, where a segment is defined to be a contiguous sequence of non-space characters.

Please note that the string does not contain any non-printable characters.

Example:

Input: "Hello, my name is John"
Output: 5

这道题目就更加简单了,主要搞清楚两点,一个是开头和结尾的空格,使用trim函数处理,第二个是连续的空格,使用“ +”进行切分,但是内置函数方法效率较低,我这里提供三种方法,如下:

    //10%
    public static int countSegments(String s) {
        if(s == null || s.equals("") || s.trim().equals(""))
            return 0;
        String[] res = s.trim().split(" +");
        return res.length;
    }

    //28%
    public int countSegments1(String s) {
        int res=0;
        for(int i=0; i<s.length(); i++)
            if(s.charAt(i)!=' ' && (i==0 || s.charAt(i-1)==' '))
                res++;
        return res;
    }

    //63%
    public int countSegments2(String s) {
        int segs = 0;
        char[] chars = s.toCharArray();
        for(int i=0;i<chars.length;i++) {
            if(chars[i]!=' ') segs++;
            while(i<chars.length && chars[i]!=' ') i++;
        }
        return segs;
    }
作者:liuchonge 发表于2017/11/14 10:57:38 原文链接
阅读:88 评论:0 查看评论

Unity Shader 学习笔记(7) 高光反射

$
0
0

Unity Shader 学习笔记(7) 高光反射

参考书籍:《Unity Shader 入门精要》
3D数学 学习笔记(8) 光照

Phong模型的逐顶点、逐像素,和Blinn模型对比:


Phong模型


逐顶点光照(Gouraud shading,高洛德着色)

Properties {
    _Diffuse ("Diffuse",Color) = (1,1,1,1)
    _Specular ("Specular",Color) = (1,1,1,1)    // 反射颜色
    _Gloss ("Gloss",Range(8.0,256)) = 20        // 高光区域大小
}

Pass中关键代码:

struct a2v {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
};

struct v2f {
    float4 pos : SV_POSITION;
    fixed3 color : COLOR0;
};

v2f vert (a2v v){
    v2f o;
    o.pos = UnityObjectToClipPos(v.vertex);

    // 下面这块是逐顶点漫反射,详见上一篇。
    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
    fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));
    fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir));

    // 计算获得出射方向r。reflect:发射方向,CG提供的函数。worldLightDir是光照方向,与L方向相反。
    fixed reflectDic = normalize(reflect(-worldLightDir,worldNormal));

    // 视觉方向v。即相机到物体的向量归一化。
    // 等价UnityWorldSpaceViewDir(mul(unity_ObjectToWorld,v.vertex))
    fixed viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld,v.vertex).xyz);

    // 高光反射系数,Phong模型公式,假设只有一个平行光源_LightColor0。
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDic,viewDir)),_Gloss);

    o.color = ambient + diffuse + specular;
    return o;
}

fixed4 frag(v2f i) : SV_Target {
    return fixed4(i.color,1.0);
}

逐像素光照(Phong shanding,Phong着色)

没有太大区别,只是把计算过程丢到了片元着色器。

struct v2f {
    float4 pos : SV_POSITION;
    float3 worldNormal : TEXCOORD0;
    float3 worldPos : TEXCOORD1;
};

v2f vert (a2v v){
    v2f o;
    o.pos = UnityObjectToClipPos(v.vertex);
    o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject);    
    o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
    return o;
}

fixed4 frag(v2f i) : SV_Target {

    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

    fixed3 worldNormal = normalize(i.worldNormal);
    fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir));

    fixed reflectDic = normalize(reflect(-worldLightDir,worldNormal));
    fixed viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDic,viewDir)),_Gloss);

    return fixed4(ambient + diffuse + specular,1.0);
}

Blinn光照模型

计算快于Phong模型。两种都是经验模型。一些情况下Blinn模型更符合实验结果。

直接修改上面Phong的逐片元代码即可。

// 视觉方向v
//fixed viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));

// 单位向量h
fixed3 halfDir = normalize(worldLightDir + viewDir);

// 套公式
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(worldNormal,halfDir)),_Gloss);

作者:l773575310 发表于2017/11/14 11:02:38 原文链接
阅读:23 评论:0 查看评论

BZOJ1497: [NOI2006]最大获利

$
0
0

Description

新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战。THU集团旗下的CS&T通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究、站址勘测、最优化等项目。在前期市场调查和站址勘测之后,公司得到了一共N个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第i个通讯中转站需要的成本为Pi(1≤i≤N)。另外公司调查得出了所有期望中的用户群,一共M个。关于第i个用户群的信息概括为Ai, Bi和Ci:这些用户会使用中转站Ai和中转站Bi进行通讯,公司可以获益Ci。(1≤i≤M, 1≤Ai, Bi≤N) THU集团的CS&T公司可以有选择的建立一些中转站(投入成本),为一些用户提供服务并获得收益(获益之和)。那么如何选择最终建立的中转站才能让公司的净获利最大呢?(净获利 = 获益之和 - 投入成本之和)

Input

输入文件中第一行有两个正整数N和M 。第二行中有N个整数描述每一个通讯中转站的建立成本,依次为P1, P2, …, PN 。以下M行,第(i + 2)行的三个数Ai, Bi和Ci描述第i个用户群的信息。所有变量的含义可以参见题目描述。

Output

你的程序只要向输出文件输出一个整数,表示公司可以得到的最大净获利。

Sample Input

5 5

1 2 3 4 5

1 2 3

2 3 4

1 3 3

1 4 2

4 5 3

Sample Output

4

HINT

【样例说明】选择建立1、2、3号中转站,则需要投入成本6,获利为10,因此得到最大收益4。【评分方法】本题没有部分分,你的程序的输出只有和我们的答案完全一致才能获得满分,否则不得分。【数据规模和约定】 80%的数据中:N≤200,M≤1 000。 100%的数据中:N≤5 000,M≤50 000,0≤Ci≤100,0≤Pi≤100。

题目传送门

woc这是什么题啊,NOI级别果然还是有点丧心病狂啊….
第一眼想到了Dp,但是半天搞不出来一个方程
于是%了一发Hanks_o的题解

我的乖乖,真的是皮皮啊
最大权闭合子图的经典模版
st向正权点(可以赚钱的)连容量为利益的边。
负权点(要花钱的)向ed连容量为花的钱的边。
图中的边(对应的利益和花费)连容量为无限大的边。
答案为总利益-最大流

为啥啊??于是开始了很久很久的思索
自己画一个图(手画)
那么我们跑dicnic
最大流的值一定是min(收益,建立基站所需花费),用总的收益值减去最大流

所以如果不利益不够,跑出来的就是收益,代表我们不会选择这个收益,所以要减去他
反之如果利益够了,那跑出来的就是花费,一样要减掉这个的花费
就得出了这个结论

那就是:得到的收益减去了建立基站的花费,就是纯收入了

好强啊….我真的是菜2333

代码如下:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct node
{
    int x,y,c,next,other;
}a[2100000];int len,last[2100000];
void ins(int x,int y,int c)
{
    int k1,k2;

    k1=++len;
    a[len].x=x;a[len].y=y;a[len].c=c;
    a[len].next=last[x];last[x]=len;

    k2=++len;
    a[len].x=y;a[len].y=x;a[len].c=0;
    a[len].next=last[y];last[y]=len;

    a[k1].other=k2;
    a[k2].other=k1;
}
int st,ed;
int h[110000],head,tail;
int list[1100000];
bool bfs()
{
    memset(h,0,sizeof(h));h[st]=1;
    head=1;tail=2;
    list[1]=st;
    while(head!=tail)
    {
        int x=list[head];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(h[y]==0&&a[k].c>0)
            {
                h[y]=h[x]+1;
                list[tail++]=y;
            }
        }
        head++;
    }
    if(h[ed]>0)return true;
    return false;
}
int findflow(int x,int f)
{
    if(x==ed)return f;
    int s=0,t;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(a[k].c>0&&h[y]==h[x]+1&&s<f)
        {
            s+=(t=findflow(y,min(a[k].c,f-s)));
            a[k].c-=t;a[a[k].other].c+=t;
        }
    }
    if(s==0)h[x]=0;
    return s;
}
int n,m,ans,sum;
int main()
{
    scanf("%d%d",&n,&m);
    st=n+m+1,ed=st+1;
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        ins(i,ed,x);
    }
    sum=0;
    for(int i=1;i<=m;i++)
    {
        int x,y,c;
        scanf("%d%d%d",&x,&y,&c);sum+=c;
        ins(i+n,x,9999999);ins(i+n,y,99999999);
        ins(st,i+n,c);
    }
    ans=0;
    while(bfs()==true)ans+=findflow(st,9999999);
    printf("%d\n",sum-ans);
    return 0;
}

by_lmy

作者:HeroDeathes 发表于2017/11/14 13:24:33 原文链接
阅读:0 评论:0 查看评论

STORM入门之(集成HDFS)

$
0
0

总体

Storm集成hdfs需要做前期工作

1.hadoop单机版安装

2.自己写hdfs demo 查看是否写入成功


首先让我们来安装hadoop 

版本:hadoop-native-64-2.6.0.tar

jdk:1.7

Hadoop部分

(1)hadoop配置文件修改

core-site.xml

<configuration>
		 <property>
             <name>hadoop.tmp.dir</name>
             <value>file:/soc/hadoop/tmp</value>
             <description>Abase for other temporary directories.</description>
        </property>     
        <property>
             <name>fs.defaultFS</name>
             <value>hdfs://10.176.63.105:9000</value>
        </property>
</configuration>
hdfs-site.xml

<configuration>
        <property>
             <name>dfs.replication</name>
             <value>1</value>
        </property>
        <property>
             <name>dfs.namenode.name.dir</name>
             <value>file:/soc/hadoop/tmp/dfs/name</value>
        </property>
        <property>
             <name>dfs.datanode.data.dir</name>
             <value>file:/soc/hadoop/tmp/dfs/data</value>
        </property>
		<property>
			<name>dfs.permissions.enabled</name>
             <value>false</value>
		</property>
</configuration>


(2)hadoop用户免密码操作:http://blog.csdn.net/yl3395017/article/details/78496979

(3)hadoop-native-64-2.6.0.tar增加解压后的文件放入到hadoop-2.6.5/lib

(4)如果在windows平台调用centos平台的hadoop ,需要在system32下加入hadoop2.6(x64)V0.2.zip中的hadoop.dll 否则会报错

(5)别忘记修改目录权限

(6)启动namenode datanode secondnamenode  脚本在hadoop-2.6.5/bin 或者是/sbin下

./start-dfs.sh

./stop-dfs.sh

(7)jps查看是否启动 namenode datanode secondnamenode 如果报错 需要查看hadoop日志


STROM部分

bolt构建

    private static HdfsBolt HdfsConfig(){
        // 输出字段分隔符
        RecordFormat format = new DelimitedRecordFormat().withFieldDelimiter("|");

        // 每1000个tuple同步到HDFS一次
        SyncPolicy syncPolicy = new CountSyncPolicy(1000);

        // 每个写出文件的大小为100MB
        FileRotationPolicy rotationPolicy = new FileSizeRotationPolicy(100.0f, FileSizeRotationPolicy.Units.MB);

        // 设置输出目录
        FileNameFormat fileNameFormat = new DefaultFileNameFormat().withPath("/soc/hadoop/tmp/dfs/data");

        // 执行HDFS地址
        HdfsBolt hdfsBolt = new HdfsBolt()
                .withFsUrl("hdfs://10.176.63.105:9000")
                .withFileNameFormat(fileNameFormat)
                .withRecordFormat(format)
                .withRotationPolicy(rotationPolicy)
                .withSyncPolicy(syncPolicy);
        return  hdfsBolt;

    }

Toplogy构建方式

builder.setBolt("Hdfs", HdfsConfig())


查询hdfs javademo

    public static void ReadFile() throws Exception {
        String uri = "hdfs://10.176.63.105:9000/soc/hadoop/tmp/dfs/data/Hdfs-1-0-1510634654752.txt";
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem. get(URI.create (uri), conf);
        InputStream in = null;
        try {
        in = fs.open( new Path(uri));
        IOUtils.copyBytes(in, System.out, 4096, false);
        } finally {
        IOUtils.closeStream(in);
        }
     }

具体的hadoop详情可以在  http://localhost:50070 查看

注意 localhost改为你自己的hadoop服务器

结果

启动storm入库生成hdfs文件成功



通过demo查询 hdfs 成功




作者:yl3395017 发表于2017/11/14 13:58:37 原文链接
阅读:0 评论:0 查看评论

leetcode: 37. Sudoku Solver

$
0
0

Q

Write a program to solve a Sudoku puzzle by filling the empty cells.

Empty cells are indicated by the character '.'.

You may assume that there will be only one unique solution.

Example

这里写图片描述

A sudoku puzzle…

这里写图片描述

…and its solution numbers marked in red.

AC

class Solution:
    """
    :type board: List[List[str]]
    :rtype: void Do not return anything, modify board in-place instead.
    """
    def solveSudoku(self, board):
        def isValid(board, x, y):
            for i in xrange(9):
                if i != x and board[i][y] == board[x][y]:
                    return False
            for j in xrange(9):
                if j != y and board[x][j] == board[x][y]:
                    return False
            i = 3 * (x / 3)
            while i < 3 * (x / 3 + 1):
                j = 3 * (y / 3)
                while j < 3 * (y / 3 + 1):
                    if (i != x or j != y) and board[i][j] == board[x][y]:
                        return False
                    j += 1
                i += 1
            return True

        def solver(board):
            for i in xrange(len(board)):
                for j in xrange(len(board[0])):
                    if(board[i][j] == '.'):
                        for k in xrange(9):
                            board[i][j] = chr(ord('1') + k)
                            if isValid(board, i, j) and solver(board):
                                return True
                            board[i][j] = '.'
                        return False
            return True

        solver(board)

if __name__ == '__main__':
    board = [[".",".","9","7","4","8",".",".","."],
             ["7",".",".",".",".",".",".",".","."],
             [".","2",".","1",".","9",".",".","."],
             [".",".","7",".",".",".","2","4","."],
             [".","6","4",".","1",".","5","9","."],
             [".","9","8",".",".",".","3",".","."],
             [".",".",".","8",".","3",".","2","."],
             [".",".",".",".",".",".",".",".","6"],
             [".",".",".","2","7","5","9",".","."]]
    Solution().solveSudoku(board)
    assert board == [["5","1","9","7","4","8","6","3","2"],
                     ["7","8","3","6","5","2","4","1","9"],
                     ["4","2","6","1","3","9","8","7","5"],
                     ["3","5","7","9","8","6","2","4","1"],
                     ["2","6","4","3","1","7","5","9","8"],
                     ["1","9","8","5","2","4","3","6","7"],
                     ["9","7","5","8","6","3","1","2","4"],
                     ["8","3","2","4","9","1","7","5","6"],
                     ["6","4","1","2","7","5","9","8","3"]]


作者:JNingWei 发表于2017/11/14 8:40:31 原文链接
阅读:3 评论:0 查看评论

leetcode: 38. Count and Say

$
0
0

Q

The count-and-say sequence is the sequence of integers with the first five terms as following:

    1.     1
    2.     11
    3.     21
    4.     1211
    5.     111221
1 is read off as "one 1" or 11.
11 is read off as "two 1s" or 21.
21 is read off as "one 2, then one 1" or 1211.
Given an integer n, generate the nth term of the count-and-say sequence.

Note:

Each term of the sequence of integers will be represented as a string.

Example 1:

Input: 1
Output: "1"

Example 2:

Input: 4
Output: "1211"

AC

class Solution(object):
    def countAndSay(self, n):
        """
        :type n: int
        :rtype: str
        """
        s = '1'
        for i in range(n-1):
            count = 1
            temp = []
            for index in range(1, len(s)):
                if s[index] == s[index-1]:
                    count += 1
                else:
                    temp.append(str(count))
                    temp.append(s[index-1])
                    count = 1
            temp.append(str(count))
            temp.append(s[-1])
            s = ''.join(temp)
        return s

class Solution2:
    # @return a string
    def countAndSay(self, n):
        seq = "1"
        for i in xrange(n - 1):
            seq = self.getNext(seq)
        return seq

    def getNext(self, seq):
        i, next_seq = 0, ""
        while i < len(seq):
            cnt = 1
            while i < len(seq) - 1 and seq[i] == seq[i + 1]:
                cnt += 1
                i += 1
            next_seq += str(cnt) + seq[i]
            i += 1
        return next_seq

if __name__ == "__main__":
    for i in xrange(1, 4):
        print Solution().countAndSay(i)


作者:JNingWei 发表于2017/11/14 9:09:17 原文链接
阅读:4 评论:0 查看评论

leetcode: 39. Combination Sum

$
0
0

Q

Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

The same repeated number may be chosen from C unlimited number of times.

Note:

All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
For example, given candidate set [2, 3, 6, 7] and target 7, 
A solution set is: 
[
  [7],
  [2, 2, 3]
]

AC

class Solution(object):
    def combinationSum(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        res = []
        candidates.sort()
        self.dfs(candidates, target, 0, [], res)
        return res

    def dfs(self, nums, target, index, path, res):
        if target < 0:
            return  # backtracking
        if target == 0:
            res.append(path)
            return 
        for i in xrange(index, len(nums)):
            self.dfs(nums, target-nums[i], i, path+[nums[i]], res)

class Solution2(object):
    def combinationSum(self, candidates, target):
        result = []
        self.combinationSumRecu(sorted(candidates), result, 0, [], target)
        return result

    def combinationSumRecu(self, candidates, result, start, intermediate, target):
        if target == 0:
            result.append(list(intermediate))
        while start < len(candidates) and candidates[start] <= target:
            intermediate.append(candidates[start])
            self.combinationSumRecu(candidates, result, start, intermediate, target - candidates[start])
            intermediate.pop()
            start += 1

if __name__ == "__main__":
    candidates, target = [2, 3, 6, 7], 7
    result = Solution().combinationSum(candidates, target)
    assert result == [[2, 2, 3], [7]]


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