活的明白

商业内幕最近发表了一篇文章说做程序员压力山大,很多人都快疯了。文中陈述了几个典型的罪状:骗子综合症,加班加点,精疲力竭等。作者指出,程序员的工作压力的根源通常是源自混乱的管理,但越来越多的压力开始来自程序员社群自身,社群中开始形成一种文化,将加班加点当成判断一个程序员是否具有奉献精神的石蕊试剂,强加到程序员身上。换句话说,如果你不在下班时间继续写代码,你就不可能成为一名合格的程序员。跟这些压力相呼应的是急速革新的各种新技术、新框架、新语言、新平台、新程序包、新SDK等的不断出现,就如火上浇油。


可事实上问题不在于此。编程,就跟写作、绘画、作曲一样,首先是一种创造性的活动,而不是一个种技术工作。当然,对一种技术或编程语言的不断练习和保持熟悉很重要,这其实就是在学习使用工具和技法,但它并不会让你本质上变成一名更优秀的程序员。它只是让你能更熟练的使用工具。而能让你成为更优秀的程序员的是学会如何思考问题,因为最终你是把脑子里思考出的逻辑转换成了一系列操作计算机的指令,让计算机遵照指令解决问题。而学习如何正确的思考——如何抽象归纳,如何组合,如何分析信息,如何自我反省——可以通过各种方式,远非只有编程一种。Paul Graham在他的精彩著作《黑客与画家》一书中说:


我发现那些最有价值的灵感的源泉都不是那些跟“计算机”这个词相关的领域,而是那些跟动手创造相关的领域。绘画就是一个比计算机理论能提供更丰富灵感的思想源泉。


拓展其它领域的技术,培养除编程之外的其它爱好,这会给你的日常工作带来巨大的帮助。程序员根本不需要没日没夜的写代码。你应该把这些时间用于和他人交流,和大家一起边喝咖啡(或你喜爱的东西)边编码、阅读、讨论。你应该把这些时间用于跑步或举重。身体锻炼给大脑补充氧气,滋养这个最神奇的器官,这才是你需要的。我三年前开始跑步。呼吸新鲜的空气、沐浴清新的阳光让我变得更加快乐,跑出几公里远离繁杂的琐事,我的脑子有了更多的时间来激发灵感。


关键是,关注心灵,关注自己,这能让你成为一个更好的程序员。你可以无止境的学习新语法,新工具,或新什么东西,但是,如果所有你做的只是编程,你实际上在跟自己背道而驰。有时候你需要全力以赴,但那是当程序中有问题需要救火时,是特殊情况,而不是日常。如果你的驻地总是有火灾,那你应该换个地方。有时候你需要埋头苦干,干上几周甚至几个月,为了让你的理想变成现实。然后是休息。相反,一味的玩命苦干只能换来越来越少的回报,是完全与成为一名更好的程序员的愿望背道而驰。去年11月,我参加了NaNoWriMo (National Novel Writers Month),这是一个非正式的比赛,参赛者要求在30天里写出一本5万字左右的书。我每天早起,花几个小时写作,然后上8个多小时的班,然而晚上继续写作。每天如此。坚持了30天。月末的时候我的身体开始透支,我病了。但这对我是有必要的,我一直有个愿望要写一本小说。之后我几个月没有写任何东西。我需要休息,要恢复平常态,要以此进步。软件开发与此无二。


商业内幕的这篇文章同时还饶有兴趣的发现“女性程序员经常坦白说在遭受骗子综合征的折磨…但越来越多的男性程序员也开始表示深有同感。”20世纪和21世纪工作中的性别问题峰回路转,最终男性也遇到类似的问题。女性第一次看到了竞争的问题侵扰男性,尤其是在那些传统的以男性为中心的行业。我相信这是生存竞争必然导致的现象,但不应出现在一个富足而且灵活的社会中。男人们看到女性对工作上非人性的现状的反应,也加入了她们的行列一起表达对现状的不满情绪。随着更多的女性进入到编程行业,她们给这些男性程序员带来了一种新的旁观者的视角。女性需要去理解她们发现的这些不幸的行业现状是男性程序员以前必须每天面对的、接受的。但事实上程序员们完全不必如此,这是一种具有强大力量的认识。


不要再让自己精疲力竭,这样不会让你成为更好的程序员。做你爱做的事,爱上更多的兴趣。你将会变的更优秀。

好的,我明白了。LR(0) 前缀 DFA 的构造可以分为以下几个步骤: 1. 对输入的文法进行扩充,添加一个起始符号 S',将 S' -> S 作为第一条产生式。 2. 构造 LR(0) 项集族,即每个项集表示了从某个状态经过某个符号可以转移到的所有状态。 3. 对每个 LR(0) 项集进行闭包运算,即将所有可能的后继符号加入该项集中,直到没有新的符号可以加入为止。 4. 对每个 LR(0) 项集进行转移运算,即对每个非终结符构造一个新的项集,表示从当前项集经过该非终结符可以转移到的所有状态。 5. 对所有项集进行编号,作为状态标识。 6. 构造前缀 DFA,即对每个状态和每个终结符构造一个转移边,表示从当前状态经过该终结符可以转移到的下一个状态。 下面给出 Java 代码实现: ```java import java.util.*; public class LR0DFA { private final Grammar grammar; // 输入文法 private final Map<LR0State, Integer> stateMap; // 状态到编号的映射 private final List<LR0State> stateList; // 状态列表 private final List<Map<String, Integer>> transitionTable; // 转移表 public LR0DFA(Grammar grammar) { this.grammar = grammar; this.stateMap = new HashMap<>(); this.stateList = new ArrayList<>(); this.transitionTable = new ArrayList<>(); build(); } // 构造 LR(0) 前缀 DFA private void build() { // 对文法进行扩充 String startSymbol = grammar.getStartSymbol(); Production augmentedProduction = new Production("S'", Collections.singletonList(startSymbol)); List<Production> productions = new ArrayList<>(grammar.getProductions()); productions.add(0, augmentedProduction); Grammar augmentedGrammar = new Grammar(grammar.getTerminals(), grammar.getNonTerminals(), startSymbol, productions); // 构造 LR(0) 项集族 LR0State startState = new LR0State(augmentedGrammar, augmentedProduction, 0); Set<LR0State> stateSet = new HashSet<>(); stateSet.add(startState); Queue<LR0State> queue = new LinkedList<>(); queue.offer(startState); while (!queue.isEmpty()) { LR0State state = queue.poll(); for (String symbol : state.getNextSymbols()) { LR0State nextState = state.go(symbol); if (!stateSet.contains(nextState)) { stateSet.add(nextState); queue.offer(nextState); } } } // 对每个 LR(0) 项集进行闭包和转移运算 for (LR0State state : stateSet) { state.closure(); } for (LR0State state : stateSet) { Map<String, LR0State> nextMap = state.getNextStateMap(); Map<String, Integer> transitionMap = new HashMap<>(); for (Map.Entry<String, LR0State> entry : nextMap.entrySet()) { String symbol = entry.getKey(); LR0State nextState = entry.getValue(); if (!stateSet.contains(nextState)) { continue; } int nextStateId = stateMap.computeIfAbsent(nextState, s -> stateList.size()); transitionMap.put(symbol, nextStateId); } stateList.add(state); stateMap.put(state, stateList.size() - 1); transitionTable.add(transitionMap); } } // 获取状态数 public int getStateCount() { return stateList.size(); } // 获取转移表 public List<Map<String, Integer>> getTransitionTable() { return transitionTable; } // 获取状态对应的编号 public int getStateId(LR0State state) { return stateMap.get(state); } } ``` 其中,LR0State 表示 LR(0) 项集,包含了该项集中的所有项以及从该项集可以转移到的下一个状态。LR0State 的 go 方法表示对该项集进行转移运算,返回一个新的项集。LR0State 的 closure 方法表示对该项集进行闭包运算,将所有可能的后继符号加入该项集中。 转移表是一个二维列表,列表的每个元素是一个 Map,表示某个状态在某个终结符下可以转移到的下一个状态的编号。状态通过 stateMap 进行编号,编号从 0 开始递增。getStateCount 方法返回状态数,getStateId 方法返回某个状态对应的编号。 使用 LR0DFA 类可以对输入的文法构造 LR(0) 前缀 DFA,获取状态数和转移表。例如,对于以下文法: ``` S -> E E -> E + T | T T -> int * T | int ``` 可以这样使用 LR0DFA 类: ```java Grammar grammar = new Grammar( Arrays.asList("int", "+", "*"), Arrays.asList("S", "E", "T"), "S", Arrays.asList( new Production("S", Collections.singletonList("E")), new Production("E", Arrays.asList("E", "+", "T")), new Production("E", Collections.singletonList("T")), new Production("T", Arrays.asList("int", "*", "T")), new Production("T", Collections.singletonList("int")) ) ); LR0DFA dfa = new LR0DFA(grammar); int stateCount = dfa.getStateCount(); List<Map<String, Integer>> transitionTable = dfa.getTransitionTable(); ``` 这样,stateCount 就是状态数,transitionTable 就是转移表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值