一个矫正代码习惯的练习记录

原代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package literatePrimes;
public class PrintPrimes {
public static void main(String[] args) {
final int M = 1000;
final int RR = 50;
final int CC = 4;
final int WW = 10;
final int ORDMAX = 30;
int P[] = new int[M + 1];
int PAGENUMBER;
int PAGEOFFSET;
int ROWOFFSET;
int C;int J;
int K;
boolean JPRIME;
int ORD;
int SQUARE;
int N;
int MULT[] = new int[ORDMAX + 1];
J = 1;
K = 1;
P[1] = 2;
ORD = 2;
SQUARE = 9;
while (K < M) {
do {
J = J + 2;
if (J == SQUARE) {
ORD = ORD + 1;
SQUARE = P[ORD] * P[ORD];
MULT[ORD - 1] = J;
}
N = 2;
JPRIME = true;
while (N < ORD && JPRIME) {
while (MULT[N] < J)
MULT[N] = MULT[N] + P[N] + P[N];
if (MULT[N] == J)
JPRIME = false;
N = N + 1;
}
} while (!JPRIME);
K = K + 1;
P[K] = J;
}
{
PAGENUMBER = 1;
PAGEOFFSET = 1;
while (PAGEOFFSET <= M) {
System.out.println("The First " + M +
" Prime Numbers --- Page " + PAGENUMBER);
System.out.println("");
for (ROWOFFSET = PAGEOFFSET; ROWOFFSET < PAGEOFFSET + RR; ROWOFFSET++){
for (C = 0; C < CC;C++)
if (ROWOFFSET + C * RR <= M)
System.out.format("%10d", P[ROWOFFSET + C * RR]);
System.out.println("");
}
System.out.println("\f");
PAGENUMBER = PAGENUMBER + 1;
PAGEOFFSET = PAGEOFFSET + RR * CC;
}
}
}
}

粗读下来就能发现的问题:

  1. 函数太长了,而且杂糅了数据生成和数据打印到页面上,两个模块的代码
  2. 变量命名太简单了,看不出实际的含义
  3. 数据生成部分的代码逻辑过于复杂,看不懂是怎么生成的数据

先从更容易看懂的数据打印部分开始重构:

PrimePrinter-refactor1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class PrimePagePrinter {
int pageNumber = 1; //PAGENUMBER
int pageOffset = 1; //PAGEOFFSET
int rowLength = 50; //RR
int colLength = 4;//CC
int M = 1000;
final int WW = 10;
final int ORDMAX = 30;
int P[];

public PrimePagePrinter(int rowLength, int colLength, int[] P) {
this.rowPerPage = rowLength;
this.colLength = colLength;
this.P = P;
this.M = P.length - 1;
}

public print() {
while (this.pageOffset <= this.M) {
this.printHeader();
this.PrintPrimes();
System.out.println("\f");
this.pageNumber += 1;
this.pageOffset += this.rowPerPage * this.colLength;
}
}

public printHeader() {
System.out.println("The First " + M +
" Prime Numbers --- Page " + this.pageNumber);
System.out.println("");
}

public printPrimes() {
for (ROWOFFSET = this.pageOffset; ROWOFFSET < this.pageOffset + this.rowPerPage; ROWOFFSET++){
for (C = 0; C < this.colLength;C++)
if (ROWOFFSET + C * this.rowPerPage <= this.M)
System.out.format("%10d", this.P[ROWOFFSET + C * this.rowPerPage]);
System.out.println("");
}
}

这一步重构主要做了:

  1. 修改了部分命名,让含义更清晰
  2. 对打印过程进行了简单的分割,分成了 printHeaderprintPrimes
Read more »

前言:

在学校的时候对Kubernetes的向往来自于对“自动编排”这一愿景的向往。实际工作中接触到以后,发现各种知识扑面而来。比起直接深入细节,弄明白为什么需要Kubenetes的这些组件,为什么这些组件之间是如此互动的等问题,能够帮助我理清楚头绪。谨以此作为学习记录。

为什么需要Kubernetes?

回到我还在学校的时候,学生信息管理系统 (aka 选课系统)属实是人手一个的项目。问题来了,如果学校在同学们的吐槽声中,真的决定选中你写的学生选课信息管理系统作为升级版本,原本在你电脑里运行的二进制文件,真的能满足同学们的需求吗?

说不定经过一番折腾真的可以。首先,我们来尝试考虑同学们在选课的需求:

  1. 准确性:选课信息要准确,不同同学之间的课程信息不能弄混
  2. 可靠性:大量同学一起选课的时候不能崩

再尝试考虑学校的需求:

  1. 充分利用资源:除了选课高峰期,其他时间,系统不应该占据过多的服务器资源,以减少学校开支
  2. 减少人工干预的成本:选课期间老师们大多忙于解答选课问题或者处理排课冲突等问题,没有过多精力关注选课系统本身的问题

原本在课上写的代码可能包括如下部分:

  • Gateway:系统前端,也负责转发流量到后端的部分
  • Admin:身份验证
  • Database:存储选课信息
  • Controller:对选课逻辑等进行检查、处理(比如需要修满本系学分,同一个学生不同课程时间有重叠需要调整或者提醒等)
Read more »

从独木桥到旷野

如果说高中是只需要埋头前进勇争上游的独木桥,那么大学就是一片未知的旷野。

前几天接到高中朋友的提问,让我介绍下NJUSE的情况。我一时哽住,说实话谈论一个院系不可能绕开讨论就读体验,仔细想想四年时间里我有收获也有不满,万般滋味实在难以总结成为最后结论。我能提供的靠谱信息,其实只有相对客观的事实。

但是我又很清楚的知道,对于大部分刚刚离开高考体系的同学们来说,认识到“事实+价值=决策”的人寥寥无几,大家都习惯了给定方向向前冲,但是从填志愿开始,大学就展现了它截然不同的特征。所以我写了这篇文章。

无论选择哪所学校,哪个院系,它都是万般可能性中的一种,高考的目标是考一个好分数,这是确定的;但是在大学里,从选专业到选课再到最终决定毕业去向,选择多得眼花缭乱。没有绝对意义上最好的选择,只有对做选择的个体来说最想要、最适合、最不会后悔的选择

其实高考也是如此,只是高压的应试教育体系不允许有不同的声音。有人觉得按照老师的指导一路前冲只考虑如何高分是无忧无虑的,就会有人觉得单一的评价体系压抑了自己的多种可能性。上大学这件事,乐观点说,我们终于拥有了更多的选择,可以尝试不同的可能性;对于不喜欢选择的同学,我只能很抱歉地说,你已经被推向了这个花花世界,你当然可以逃避,可以继续躲在师长的羽翼下,但是现实是,你是那个承担选择的后果的人,与其为别人的决定买单,为什么不一开始就按照自己的心意选择呢?途中可能会走弯路,可能会后悔,但是这全都是你的选择、你的经历、你的人生。

所以从填志愿开始,自己决定要奔向旷野何方吧。

所有人的建议,都是有色眼镜后的所见

既然高中埋头赶路的模式已经不适合大学,那么如何在大学里做决定呢?

首先,得要有这个意识。例如说,可能会有辅导员告诉你只要好好搞绩点做德育活动就能保研,可是有可能到9月保研季规则改动,或是到时候才发现原来有些思政活动对导师而言屁用没有——只有自己搜集信息,才能得出属于自己的判断,而不是人云亦云,把选择权无形的拱手相让。

Read more »

四年前入学的时候应该想不到自己真的能带着两段实习和一个符合选择CS初心的预期的工作offer毕业。如果能重来一遍,有些事情我希望我能早点做到,或是继续保持,或是不要做。在这篇文章里简单写写。

早点做到

多多提问

对内向型人来说提问可能是困难的,如果担心自己在提问中被看不起,提问就会变得更加困难。

但是对于新手来说,只要掌握了正确的提问方法就No Stupid Question。同时应该解构“提问”这一动作的含义:提问不代表你能力不行,不假思索的提问才会影响能力的成长,经过思考以后求助才能帮助你摆脱目前的困境。

可能大一早点想通这点,绩点就不至于如此凄惨了(

喜欢就享受,不喜欢就趁早摆脱

大二的时候一度非常怀疑自己的选择,但是这个专业和学校又的确是我自己选的,不出于所谓的就业前景、不出于所谓的热门,就只是我的兴趣结合我需要的现实资源的考量。后来我尝试着捕捉那些让我感到发自内心快乐的时刻,我终于发现,原来我讨厌的不是学习CS的过程,是不合理的体系设计。

想明白一点以后,我开始寻找新的可能性,比如不读研尝试找工,也如愿摆脱了让我身心俱疲的环境与节奏,找到让我舒适的新的选项。享受快乐的瞬间;对折磨的时刻,不要坐以待毙,跑起来!

继续保持

Read more »

关于选题

事实上在做毕设之前我从来没有接触过机器学习相关的科研或者项目,实习做的也不是这个方向。是在和导师沟通的过程中,觉得这个题目有点意思,加上之前没怎么做过研究,于是脑子一热答应选了这个如导师所言”有挑战性”的选题。

虽然做的过程中经常要死要活,也一度非常迷茫自己到底能不能做完,但是因为最开始的确是对选题感兴趣,所以倒也有不少苦中作乐或者惊觉“Eureka”的时刻。毕竟本科生比较少会在毕设上被为难,所以抱着“只要认真做了一定能过”的心态,去做些自己感兴趣的尝试,也不枉费投入的时间与精力。

从零开始快速恶补机器学习——面向毕设学习机器学习

  • 系统性的阅读:找一本教材。能动手跟着做练习最好,如果时间有限,其实重点熟悉与自己的毕设有关的方面就够了,其他的反正一时半会用不上,用到了再说。

  • 论坛:(eg:Reddit,Stackoverflow)找更亲民、短平快、面向具体毕设主题的材料。

  • Chatgpt:学习一些基本的概念,或者是复习。注意:GPT只能说人话,不能保证正确,留个心眼,在实践中验证。对于基础知识,大概率材料已经在它的训练数据里,所以拿不准的时候还是会问它。

因为我的毕设本质做的是优化问题,所以针对毕设问题来学习对我来说就是:关注性能优化,可以少看公式,多关注性能衡量指标的原理,具体方法的原理先放一放。

阅读文献

  • Zetero:读文献的时候划重点,做批注,对文献类型分类,导出引用都很方便。
  • ChatPDF - Chat with any PDF!:在读文献初期,对所做领域所知甚少的时候,通过交互式的提问可以更快了解一篇论文是否对自己的毕设有帮助。
  • 学会读摘要:
    • 背景是什么:与你的毕设题目是否相关
    • 过去的研究局限是什么:补充关于现有研究的知识,可能会启发思路
    • 该论文提出的解决方案是什么:对你的主题是否有启发

对我来说:因为我的毕设本质是一个已有方案的优化问题,所以读文献花了很长时间。原因是需要了解:我的问题场景下已经有什么优化方法、是否有效、是否适用于已有方案。

做实验

Read more »

之前分享时间有限,文字稿整理了更多内容

我的背景

  • 无亮眼绩点——40%上下浮动
  • 无竞赛——美赛只有一个水奖,没有ACM、花旗杯、大创
  • 进组经历——无 第一次接触科研是在毕设期间

如果把找实习找工作比做牌桌,我猜我的开局应该和大部分人都是比较相似的,希望大家到最后不会觉得“我做不到”,而是“听起来我也行”。

写在前面

找实习和秋招春招的思路大致都是相似的。市场行情、你的期望等等因素都会有变化,所以对我来说授人以鱼不如授人以渔,对在座的各位来说,具有可成长的思维比照搬经验更重要。

具有如下心态会对你的找工之旅有些帮助:

  • 忌刻舟求剑。和往年人对比是不现实的,因为这两年情况变化很快,和身边人对比也不是一个好主意,因为你们偏好的职业路径、面对的机会与挑战不尽相同。把别人当成参照物会徒增自我怀疑。如果羡慕别人的offer的话,把别人当成可以对齐模仿的案例才是成长性的思维。
  • 不要把面试结果当成是一种评判(Judgement),而应该是一种反馈(Feedback)面试是否能通过取决于很多因素,比如面试的部门是否急需人,你们气场是否相合。评判可能是一种噪音,但是反馈是应当是有利于你调整的信号。每一次面试都可以学到东西,不管是面试技巧上的、技术上的还是对行业的理解上。
  • 抓住每一次机会,不要等到做好准备。很多时候大家可能会觉得自己没准备好或者不足以去投一些看起来很高大上的大厂。但是不投怎么知道自己没机会呢?而且投简历和面试是一件投入极小但是回报极大的事情,大不了当别人免费给你做面试训练。看到内推就大胆去问、看到岗位招聘就尝试去投,来了面试就面。适应面试套路需要时间,尝试的越多,在机会来临的时候就越有机会抓住。
  • 资源是有限的,需要权衡取舍。很多公司只允许你投递有限数量的岗位,或者是有优先级顺序;你自己的时间精力也是有限的。勇气不等于莽撞,在争取之前,需要确认自己是否真的愿意为此下注。这需要你了解你面对的机会能打开怎样的大门,以及你自己想要什么。

写简历+投递

写简历是了解自己的过程,投递是了解市场行情的过程。

Read more »

是对DP-IS-EASY!-5-Steps-to-Think-Through-DP-Questions的翻译记录,原题是 Target Sum(目标和)

DP很容易!5步思考DP问题

注意:这不是一个规范化、完美优化的DP解决方案。我们已经有足够多这样的东西了。这篇文章将带领你了解动态规划背后的思考过程,让你能够自己解决这些问题。

类别

大多数动态规划问题可以归结为几个类别。识别类别很重要,因为它允许我们将一个新问题转化成我们已知的问题。转化意味着使用框架,而不是将另一个问题的解决方法复制到当前问题中。你必须明白每个DP问题都是不同的。

问题:在继续之前将此问题标识为以下类别之一。

  • 0/1背包
  • 无界背包
  • 最短路径(例如:独特的路径I/II)
  • 斐波那契数列(例如:房子小偷,跳跃游戏)
  • 最长公共子串/子序列

答案:0/1背包

为什么是0/1背包?我们的“容量”是我们想达到的目标“S”。我们的“物品”是输入子集中的数字,物品的“重量”是数字本身的值。这个问题遵循0/1背包而不是无界背包,因为我们只能使用每个数字一次。

变化是什么?这个问题与标准背包问题的变化在于,我们必须将子集中的所有物品添加到我们的背包中。我们可以将问题重新构成为将当前数字的正值或负值添加到我们的背包中,以达到目标容量“S”。

Read more »

这里的从零是字面意思,不管是刚开始找实习的同学,还是因为考研不幸落榜匆忙投入春招的同学,这篇文章是为之前完全没有写过简历的你准备的!

这一篇是对我实习经验分享中写简历部分的具体拓展,对其他内容感兴趣也可以移步

前期准备——拉清单

清单内容如下:

  • 所有专业相关课程
    • 不管你认为有多水都要写出来
    • 有项目/课设/代码的课程要把代码和实验报告找到;整理好上传到Github/博客上,之后根据简历排布情况置顶重要项目的仓库
    • 如果没有代码等材料,尽量回忆课程主要内容,列出大纲
  • 所有专业相关活动
    • 大创、技术社团活动、数模比赛、美赛等
    • 专业内容弱相关的活动可以记下来,只是写进简历的优先级比上述略低
  • 考过的证书
    • 四六级成绩证明,雅思托福(如果有)
    • 或者你认为能体现你能力的其他证书

开始动笔

先来看一份来自CMU的简历

是不是看起来很简洁很干货?我原来用的工具现在有人反映总是会泄露个人隐私,就不推荐了。可以使用Overleaf或者自行查找类似模板。

好的,现在让我们来写简历,争取像上述简历一样一页写完 (*^_^*)

Read more »

Chatgpt会威胁人类吗

大概会威胁到脑子空空的人。

最早注意到Chatgpt是在豆瓣看到一个测试它的帖子。当时我对帖子里“AI具有鉴赏、哲学思考的可能性从而让人感到威胁”的观点有所不同意。在我的一番“抬杠”下,我发现Chatgpt会从提问里学习提问者的话术再生成回答(也许是In-context learning的一种表现?),因此提问者实际上是被自己的才华惊讶而非Chatgpt。而且仔细推敲,Chatgpt的答案实际上欠缺逻辑,也欠缺事实,信息量有限。

因此,我当时对Chatgpt的判断是:

  • 一只人类友好的学舌鹦鹉,在处理文书、工作邮件等有模版需要填内容的文件表现优异
  • 只靠Chatgpt,是没有逻辑和信息量的

人一直认为创造力是人的独有,所以人们能用Chatgpt创作小说的时候,不免又有惊恐的声音出现。但是Chatgpt更像是一个初步的索引。比如让写小说大纲,它能洋洋洒洒写出一篇。然而创作大纲本身有规律可循,网上也有不少教程总结过。Chatgpt学习了这部分语料而人没有学习就会让人觉得不明觉厉。但是对于精于创作的人(或者比较挑剔的人)来说,大纲就只是大纲,缺乏更多细节。

综上,我认为该感到恐慌的人,是所书写的文字材料本身就是套话空话,信息量少的类型。还有一群人,或许不恐慌,但是需要小心被新时代人工智能的洪水淹没的可能———没有办法判断别人话语里逻辑和事实的人,也许很容易被Chatgpt给忽悠了。

逻辑、理性和创造力,或许始终是人类的诺亚方舟。

Chatgpt是生产力新突破吗

可以是,取决于科技巨头和开发者们能多大程度弥补Chatgpt的缺陷并创造更多的可能性。

Read more »

我的背景

本科CS科班,无竞赛无比赛绩点在中游保研边缘,简历上主要是偏后端底层的课设,有一段4个月字节iOS客户端实习经历,秋招开始的时候在微软暑期实习,做的后端相关,时长3个月。

Offer情况和时间线

7月底暑期实习期间就开始同步秋招,在9月份初拿到了宁德时代的offer,因为薪资不满意+觉得秋招还有机会拒了,9月中旬拿到了Thoughtworks年包税前不到20w的offer,之后屡战屡挂,10月中下旬进了菊花厂大鱼池,微软暑期转正最终因为没有hc在11月被挂了,12月初侥幸被捞上岸拿到了阿里后端年包40w的offer

面试了大概30+场,笔试次数大概不相上下,面过的企业包括国内外科技大厂,国内外金融机构,新能源/汽车/传统行业也有涉及。

插播一个地狱笑话:

我一位在大厂实习过的朋友有一次神神秘秘的说自己和HR聊天得到了一个行业内幕。让ta讲的时候,ta先问了我一个问题:假如你是一个小团队的leader,如果你想了解竞争对手类似部门的组织架构,你会怎么办呢?

我说,我会让HR或者猎头挖竞争对手同类部门的大头兵或是senior程序员的墙脚,面试的时候提问我想要知道的问题。我朋友接着问:可是你们部门没hc怎么办?我说那就在最后一轮或者HR面提高面试难度挂掉对方。我朋友大惊,说你怎么知道HR就是这样说的。

那会我还在秋招中挣扎,我只能苦笑说这都是我被疯狂捞起涮面试KPI养成的直觉。

今年情况并不乐观,失败是家常便饭,但是失败不意味着结束,每一次面试都能让我更熟悉招聘的套路,也更熟悉我的优势和缺点,让我明确我不能接受怎样的企业风格。只有不怕失败才能不断的去尝试,修正、确认自己的策略。

我稳住求职季心态苟到最后年包翻番的tips:

第一目标是不失业

Read more »