首页 文章 精选 留言 我的

精选列表

搜索[权限提升],共10000篇文章
优秀的个人博客,低调大师

使用开源计算引擎提升Excel格式文件处理效率

对Excel进行解析\生成\查询\计算等处理是Java下较常见的任务,但Excel的文件格式很复杂,自行编码读写太困难,有了POI\EasyExcel\JExcel等类库就方便多了,其中POI最为出色。 POI具有全面而细致的xls读写能力 POI可读写多种Excel文件格式,既支持古老的二进制格式(xls),也支持现代的OOXML格式(xlsx),既支持全内存一次性读写,也支持小内存流式读写。POI为大量Excel元素设计了相应的JAVA类,包括workbook、printer、sheet、row、cell,其中,与cell相关的类包括单元格样式、字体、颜色、日期、对齐、边框等。仅单元格样式类,方法就超过了四十个,可进行最全面最细致的读写操作。 POI的读写功能很底层 POI的读写功能全面而细致,但细致也意味着过于底层,开发者必须从头写起,自己处理每一处细节,即使简单的操作也要编写大量代码。比如,读入首行为列名的行式xls: FileInputStream fileInputStream = new FileInputStream("d:\\Orders.xls"); // get the excel book Workbook workbook = new HSSFWorkbook(fileInputStream); if (workbook != null) { // get the first sheet Sheet sheet = workbook.getSheetAt(0); if (sheet != null) { //get the col name/first line Row rowTitle = sheet.getRow(0); // first line if (rowTitle != null) { int cellTitles = rowTitle.getPhysicalNumberOfCells(); // get column number for (int i = 0; i < cellTitles; i++) { Cell cell = rowTitle.getCell(i); //the cell! if (cell != null) { System.out.print(cell.getStringCellValue() + " | "); } } } //get the value/other lines int rows = sheet.getPhysicalNumberOfRows(); // get line number for (int i = 1; i < rows; i++) { Row row = sheet.getRow(i); // get row i if (row != null) { int cells = row.getPhysicalNumberOfCells(); // get column number for (int j = 0; j < cells; j++) { // line number and row number System.out.print("[" + i + "-" + j + "]"); Cell cell = row.getCell(j); // the cell! if (cell != null) { int cellType = cell.getCellType(); Object value = ""; switch (cellType) { case HSSFCell.CELL_TYPE_STRING: // string value = cell.getStringCellValue(); break; case HSSFCell.CELL_TYPE_BLANK: // 空 break; case HSSFCell.CELL_TYPE_BOOLEAN: // boolean value = cell.getBooleanCellValue(); break; case HSSFCell.CELL_TYPE_NUMERIC: // number if (HSSFDateUtil.isCellDateFormatted(cell)) { // date number Date date = cell.getDateCellValue(); value = new DateTime(date).toString("yyyy-MM-dd HH:mm:ss"); }else { // normal number // change to string to avoid being too long cell.setCellType(HSSFCell.CELL_TYPE_STRING); value = cell; } break; case HSSFCell.CELL_TYPE_ERROR: throw new RuntimeException("data type mistaken"); } System.out.println(value); } } } System.out.println("end of the "+i+" line"); } System.out.println("end of the value lines======================================="); } } 行式xls是最常见的格式,但POI并没有为此提供方便的处理方法,只能按照workbook->sheet->line->cell的顺序进行循环解析,造成了如此繁琐的代码。 这还只是将数据简单读出来,如果下一步想再处理数据,还要事先转为结构化数据对象,比如ArrayList<实体类>或HashMap,代码就更繁琐了。 POI查询计算困难 解析Excel并不是目标,我们通常还要对这些文件进查询计算,但POI作为Excel的解析类,没有也不合适再提供相关的方法,只能用JAVA手工硬写。比如基础的分组汇总运算,JAVA代码大概这样: Comparator<salesRecord> comparator = new Comparator<salesRecord>() { public int compare(salesRecord s1, salesRecord s2) { if (!s1.salesman.equals(s2.salesman)) { return s1.salesman.compareTo(s2.salesman); } else { return s1.ID.compareTo(s2.ID); } } }; Collections.sort(sales, comparator); ArrayList<resultRecord> result=new ArrayList<resultRecord>(); salesRecord standard=sales.get(0); float sumValue=standard.value; for(int i = 1;i < sales.size(); i ++){ salesRecord rd=sales.get(i); if(rd.salesman.equals(standard.salesman)){ sumValue=sumValue+rd.value; }else{ result.add(new resultRecord(standard.salesman,sumValue)); standard=rd; sumValue=standard.value; } } result.add(new resultRecord(standard.salesman,sumValue)); Java编码实现计算不仅繁琐,而且存在架构性缺陷。代码很难复用,数据结构和计算代码通常会耦合在一起,如果数据结构发生变化,代码就要重写。查询计算的要求灵活多变,而Java作为编译型语言,每次修改代码都要重启应用,维护工作量大,系统稳定性差。 POI成熟稳定,但读写能力过于底层,且未提供查询计算能力,直接基于POI完成Excel文件的处理(特别是查询计算)的开发效率很低。如果针对POI进行封装,形成简单易用的高级读写函数,并额外提供查询计算能力,就能大幅度提高开发效率了。 esProc SPL就是其中的佼佼者。 SPL内置高级读写函数 SPL是JVM下开源的计算引擎,它对POI也进行了封装,内置简单易用的高级函数,可解析\生成各类格式规则或不规则的xls,并自动生成结构化数据对象。 解析格式规则的行式Excel,SPL提供了T函数。比如解析前面的xls文件,用封装前的POI要几十行,封装后只要一句: =T("d:\Orders.xls") 解析行式Excel是很常见的任务,SPL用T函数封装了POI的功能,接口简单易用。无论xls还是xlsx,T函数都可以统一解析。可自动进行类型转换,开发者无须在细节浪费时间。T函数可自动区分首行的列名和其他行的数据,并根据列名创建序表(SPL的结构化数据对象)并填入数据: 读入并解析成序表后,就可以使用SPL提供的丰富的结构化数据处理方法了: 取第3条记录:A1(3) 取后3条记录:A1.m([-1,-2,-3]) 取记录的字段值:A1(3).Amount*0.05 修改记录的字段值:A1(3).Amount = A1(3). Amount*1.05 取一列,返回集合:A1.(Amount) 取几列,返回集合的集合:A1.([CLIENT,AMOUNT]) 追加记录:A1.insert(200,"APPL",10,2400.4,date("2010-10-10")) 先按字段取再按记录序号取:A1.(AMOUNT)(2);等价于先按记录序号取再按字段取:A1(2).AMOUNT 解析格式较不规则的行式xls,SPL提供了xlsimport函数,内置丰富而简洁的读取功能: 没有列名,首行直接是数据:file("D:\Orders.xlsx").xlsimport() 跳过前2行的标题区:file("D:/Orders.xlsx").xlsimport@t(;,3) 从第3行读到第10行:file("D:/Orders.xlsx").xlsimport@t(;,3:10) 只读取其中3个列:file("D:/Orders.xlsx").xlsimport@t(OrderID,Amount,OrderDate) 读取名为"sales"的特定sheet:file("D:/Orders.xlsx").xlsimport@t(;"sales") 函数xlsimport还具有读取倒数N行、密码打开文件、读大文件等功能,这里不再详述。 解析格式很不规则的xls,SPL提供了xlscell函数,可以读写指定sheet里指定片区的数据,比如读取第1个sheet里的A2格: =file("d:/Orders.xlsx").xlsopen().xlscell("C2") 配合SPL灵活的语法,就可以解析自由格式的xls,比如将下面的文件读为规范的二维表(序表): 这个文件格式很不规则,直接基于POI写Java代码是个浩大的工程,而SPL代码就简短得多: 生成规则的行式xls,SPL提供了xlsexport函数,用法也很简单。比如,上面例子的解析结果是个序表,存在SPL的A1格中,下面将A1写入新xls的第一个sheet,首行为列名,只要一句代码:=file("e:/result.xlsx").xlsexport@t(A1) xlsexport函数的功能丰富多样,可以将序表写入指定sheet,或只写入序表的部分行,或只写入指定的列:=file("e:/scores.xlsx").xlsexport@t(A1,No,Name,Class,Maths) xlsexport函数还可以方便地追加数据,比如对于已经存在且有数据的xls,将序表A1追加到该文件末尾,外观风格与原文件末行保持一致:=file("e:/scores.xlsx").xlsexport@a(A1) 不规则片区写入数据,可以使用前面的xlscell函数。比如,xls中蓝色单元格是不规则的表头,需要在相应的白色单元格中填入数据,如下图: 直接用POI要大段冗长的代码,而SPL代码就简短许多: 注意,第6、9、11行有连续单元格,SPL可以简化代码一起填入,POI只能依次填入。 SPL提供足够的查询计算能力 查询计算是Excel处理任务的重点,SPL提供了丰富的计算函数、字符串函数、日期函数,以及标准SQL语法,不仅支持日常的xls计算,也能计算内容不规则的xls和逻辑复杂的xls。 SPL提供了丰富的计算函数,可直接完成基础计算。比如前面的分组汇总,只要一句: A1.groups(SellerId;sum(Amount)) 更多计算: 条件查询:A1.select(Amount>1000 && Amount<=3000 && like(Client,"S")) 排序:A1.sort(Client,-Amount)" 去重:A1.id(Client)" 关联两个xlsx:join(T("D:/Orders.xlsx"):O,SellerId; T("D:/Employees.xls"):E,EId).new(O.OrderID,O.Client,O.SellerId,O.Amount,O.OrderDate, E.Name,E.Gender,E.Dept)" TopN:T("D:/Orders.xls").top(-3;Amount) 组内TopN (开窗函数):T("D:/Orders.xls").groups(Client;top(3,Amount)) SPL支持大量日期函数和字符串函数,代码量更短,开发效率更高。比如: 时间类函数,日期增减:elapse("2020-02-27",5) //返回2020-03-03 星期几:day@w("2020-02-27") //返回5,即星期4 N个工作日之后的日期:workday(date("2022-01-01"),25) //返回2022-02-04 字符串类函数,判断是否全为数字:isdigit("12345") //返回true 取子串前面的字符串:substr@l("abCDcdef","cd") //返回abCD 按竖线拆成字符串数组:"aa|bb|cc".split("|") //返回["aa","bb","cc"] SPL还支持年份增减、求年中第几天、求季度、按正则表达式拆分字符串、拆出SQL的where或select部分、拆出单词、按标记拆HTML等功能。 SPL提供了标准SQL语法,可以像对数据库表一样直接对xls文件进行查询,极大地降低了数据库程序员的学习门槛: filter:$select * from d:/sOrder.xlsx where Client like '%S%' or (Amount>1000 and Amount<=2000)sort:$select * from sales.xls order by Client,Amont descdistinct:$ select distinct(sellerid) from sales.xls group by…having:$select year(orderdate) y,sum(amount) s from sales.xls group by year(orderdate) having sum(amount)>=2000000join:$select e.name, s.orderdate, s.amount from sales.xls s left join employee.xlsx e on s.sellerid= e.eid SPL支持SQL-92标准中大部分语法,包括集合计算、case when、with、嵌套子查询等,详见<a href="http://c.raqsoft.com.cn/article/1638869916433" rel="nofollow">《没有 RDB 也敢揽 SQL 活的开源金刚钻 SPL》</a> 内容不规则的xls,一般的类库都无能为力,SPL语法灵活函数丰富,可轻松解决处理。比如Excel单元格里有很多”key=value”形式的字符串,需要整理成规范的二维表,以进行后续计算: 逻辑复杂的计算,SQL和存储过程都难以实现,SPL的计算能力更强,可轻松解决此类问题。比如,计算某支股票最长的连续上涨天数: SPL支持更优的应用架构 SPL是解释型语言,提供JDBC接口,可以用SQL或存储过程的形式被JAVA集成,不仅降低了架构的耦合性,还能支持热切换。SPL还支持多种数据源,并支持跨数据源计算。 SPL提供了JDBC接口,可被JAVA轻松调用。简单的SPL代码可以像SQL一样,直接嵌入JAVA,比如条件查询: Class.forName("com.esproc.jdbc.InternalDriver"); Connection connection =DriverManager.getConnection("jdbc:esproc:local://"); Statement statement = connection.createStatement(); String str="=T(\"D:/Orders.xls\").select(Amount>1000 && Amount<=3000 && like(Client,\"*S*\"))"; ResultSet result = statement.executeQuery(str); SPL支持计算外置,可降低计算代码和前端应用的耦合性。复杂的SPL代码可以先存为脚本文件,再以存储过程的形式被JAVA调用: Class.forName("com.esproc.jdbc.InternalDriver"); Connection conn =DriverManager.getConnection("jdbc:esproc:local://"); CallableStatement statement = conn.prepareCall("{call scriptFileName(?, ?)}"); statement.setObject(1, "2020-01-01"); statement.setObject(2, "2020-01-31"); statement.execute(); SPL是解释型语言,通过外置代码可实现热切换。解释型语言无须编译,修改后可立即执行,无须重启JAVA应用,可降低维护工作量,提高系统稳定性。 SPL支持多种文件数据源,除了xls外,SPL还能读写csv\txt\XML\Json等文件,比如对txt进行条件查询: T("sOrders.txt").groups(SellerId;sum(Amount)) $select * from d:/sOrders.txt where Client like '%S%' or (Amount>1000 and Amount<=2000) SPL支持跨数据源计算,比如xls和txt的关联计算: =join(T("D:/Orders.xlsx"):O,SellerId; T("D:/Employees.txt"):E,EId).new(O.OrderID,O.Client,O.SellerId,O.Amount,O.OrderDate, E.Name,E.Gender,E.Dept)" SPL还能访问各类关系型数据库,WebService、Restful等网络服务, Hadoop、redis、Kafka、Cassandra等NoSQL。 POI只适合简单的xls解析\生成任务,且未提供查询计算能力。SPL对POI进行了封装,内置高级读写函数,不仅可以大幅简化代码,还能进行较不规则甚至很不规则的xls解析\生成任务。SPL额外提供了强大的计算能力,不仅支持日常的Excel查询计算,还可计算内容不规则的xls和逻辑复杂的xls。SPL支持更优的应用架构,可实现代码低耦合和热切换,支持多种数据源和跨数据源计算。 SPL资料 SPL官网 SPL下载 SPL源代码 欢迎对SPL有兴趣的加小助手(VX号:SPL-helper),进SPL技术交流群 欢迎关注我的公告号:字母哥杂谈,回复003赠送作者专栏《docker修炼之道》的PDF版本,30余篇精品docker文章。字母哥博客:zimug.com

优秀的个人博客,低调大师

OpenSearch 2.2.0 发布,提升构建性能,升级到 Lucene 9.3

AWS OpenSearch 2.2.0 发布了,OpenSearch 是 AWS 自 Elasticsearch 7.10.2 的开源搜索和分析引擎。 新版本改进内容包括: Features/Enhancements Task consumer Integration (#2293) (#4141) [Backport 2.x] [Segment Replication] Add SegmentReplicationTargetService to orchestrate replication events. (#4074) Support task resource tracking in OpenSearch (#3982) (#4087) Making shard copy count a multiple of attribute count (#3462) (#4086) [Backport 2.x] [Segment Rreplication] Adding CheckpointRefreshListener to trigger when Segment replication is turned on and Primary shard refreshes (#4044) Add doc_count field mapper (#3985) (#4037) Parallelize stale blobs deletion during snapshot delete (#3796) (#3990) [Backport 2.x] [Segment Replication] Add a new Engine implementation for replicas with segment replication enabled. (#4003) [Backport 2.x] Adds a new parameter, max_analyzer_offset, for the highlighter (#4031) Update merge on refresh and merge on commit defaults in Opensearch (Lucene 9.3) (#3561) (#4013) Make HybridDirectory MMAP Extensions Configurable (#3837) (#3970) Add option to disable chunked transfer-encoding (#3864) (#3885) Introducing TranslogManager implementations decoupled from the Engine [2.x] (#3820) Changing default no_master_block from write to metadata_write (#3621) (#3756) Bug Fixes OpenSearch crashes on closed client connection before search reply when total ops higher compared to expected (#4143) (#4145) Binding empty instance of SegmentReplicationCheckpointPublisher when Feature Flag is off in IndicesModule.java file. (#4119) Fix the bug that masterOperation(with task param) is bypassed (#4103) (#4115) Fixing flaky org.opensearch.cluster.routing.allocation.decider.DiskThresholdDeciderIT.testHighWatermarkNotExceeded test case (#4012) (#4014) Correct typo: Rutime -> Runtime (#3896) (#3898) Fixing implausibly old time stamp 1970-01-01 00:00:00 by using the timestamp from the Git revision instead of default 0 value (#3883) (#3891) Infrastructure Correctly ignore depandabot branches during push (#4077) (#4113) Build performance improvements (#3926) (#3937) PR coverage requirement and default settings (#3931) (#3938) [Backport 2.x] Fail build on wildcard imports (#3940) Don't run EmptyDirTaskTests in a Docker container (#3792) (#3912) Add coverage, gha, jenkins server, documentation and forum badges (#3886) Unable to use Systemd module with tar distribution (#3755) (#3903) Ignore backport / autocut / dependentbot branches for gradle checks (#3816) (#3825) Setup branch push coverage and fix coverage uploads (#3793) (#3811) Enable XML test reports for Jenkins integration (#3799) (#3803) Maintenance OpenJDK Update (July 2022 Patch releases) (#4023) (#4092) Update to Lucene 9.3.0 (#4043) (#4088) Bump commons-configuration2 from 2.7 to 2.8.0 in /plugins/repository-hdfs (#3764) (#3783) Use bash in systemd-entrypoint shebang (#4008) (#4009) Bump com.gradle.enterprise from 3.10.1 to 3.10.2 (#3568) (#3934) Bump log4j-core in /buildSrc/src/testKit/thirdPartyAudit/sample_jars (#3763) (#3784) Added bwc version 1.3.5 (#3911) (#3913) Update to Gradle 7.5 (#3594) (#3904) Update Netty to 4.1.79.Final (#3868) (#3874) Upgrade MinIO image version (#3541) (#3867) Add netty-transport-native-unix-common to modules/transport-netty4/bu… (#3848) (#3853) Update outdated dependencies (#3821) (#3854) Added bwc version 2.1.1 (#3806) Upgrade netty from 4.1.73.Final to 4.1.78.Final (#3772) (#3778) Bump protobuf-java from 3.21.1 to 3.21.2 in /plugins/repository-hdfs (#3711) (#3726) Upgrading AWS SDK dependency for native plugins (#3694) (#3701) Refactoring [Backport 2.x] Changes to encapsulate Translog into TranslogManager (#4095) (#4142) Deprecate and rename abstract methods in interfaces that contain 'master' in name (#4121) (#4123) [Backport 2.x] Integrate Engine with decoupled Translog interfaces (#3822) Deprecate class FakeThreadPoolMasterService, BlockMasterServiceOnMaster and BusyMasterServiceDisruption (#4058) (#4068) Rename classes with name 'MasterService' to 'ClusterManagerService' in directory 'test/framework' (#4051) (#4057) Deprecate class 'MasterService' and create alternative class 'ClusterManagerService' (#4022) (#4050) Deprecate and Rename abstract methods from 'Master' terminology to 'ClusterManager'. (#4032) (#4048) Deprecate public methods and variables that contain 'master' terminology in class 'NoMasterBlockService' and 'MasterService' (#4006) (#4038) Deprecate public methods and variables that contain 'master' terminology in 'client' directory (#3966) (#3981) [segment replication]Introducing common Replication interfaces for segment replication and recovery code paths (#3234) (#3984) Deprecate public methods and variables that contain 'master' terminology in 'test/framework' directory (#3978) (#3987) [Backport 2.x] [Segment Replication] Moving RecoveryState.Index to a top-level class and renaming (#3971) Rename and deprecate public methods that contains 'master' in the name in 'server' directory (#3647) (#3964) [2.x] Deprecate public class names with master terminology (#3871) (#3914) [Backport 2.x] Rename public classes with 'Master' to 'ClusterManager' (#3870) Revert renaming masterOperation() to clusterManagerOperation() (#3681) (#3714) Revert renaming method onMaster() and offMaster() in interface LocalNodeMasterListener (#3686) (#3693) 详细每个版本的改进内容请看 https://gitee.com/mirrors/OpenSearch-Project/tree/main/release-note

优秀的个人博客,低调大师

如何通过A/B测试提升Push推送消息点击率?

618电商节火热进行中,某电商App准备向用户推送一条全局活动消息,运营准备了两个推送文案: 文案A:年中囤货我们更懂你,没有大优惠怎敢惊动你:美妆个户,户外运动,医疗健康,一站式备齐,点击>> 文案B:全场特价1折起,跨店满减满300-30,会员更有折上折,6.1激情预售开启,现在就抢,一价到底,点击>> 哪个文案更能打动用户? 我们可以用消息推送来做个A/B测试来确定推送的文案。各选择0.5%的活跃用户,推送不同的文案后分析用户的点击量数据。实际效果如下: 文案A的点击率为:3.3% 文案B的点击率为:11.4% 事后分析,文案B中有用户可直观获取数字价值的促销方案,对用户有较大的吸引力,因此全量推送文案B无疑能让用户点击率和转化率更上一层楼。 应用消息推送的A/B测试功能,支持针对不同文案、不同人群、不同时间进行消息推送对比测试,并在多组对比结果中,选择效果更好地文案或者标签人群进行自动补发,智能化实现最优的推送测试,提高推送点击率。 运营人员会使用推送通知来提高应用的日活或者唤醒沉默用户,让用户为他们的偏好投票,也让运营用最少的成本达到测试目的,继而在全量推送中达到最好的推送效果。 集成华为推送服务就可以使用推送服务的A/B测试功能,推送通知实验可以对推送通知的标题、文案、点击动作甚至是不同人群在不同时间进行消息推送对比测试等进行分组测试。可基于华为分析输出的用户属性、受众群组等条件将实验目标用户按比例分成不同分组,每个组添加不同的策略。然后根据华为分析服务得出不同分组的用户数据,如点击率,转化率等。 华为推送服务A/B测试推送效果 集成步骤 首先,使用推送通知类A/B测试之前,需要集成华为推送服务,可以参考推送服务官方文档进行集成。 操作流程 集成推送服务后,需要在App Gallery Connect上对文案进行配置,下面我会结合一个具体的案例讲解操作步骤。 假如你是一位电商App的运营,平台正在做红包营销活动。你想要对平台所有用户推送优惠券到账消息,你设置了两组不同的文案,为了测试出内容最优(打开率最高)的一组文案,随机对App用户发送消息进行A/B测试。 首先登录App Gallery Connect网站,选择“我的项目”在左侧导航栏中选择“增长 > A/B测试”,找到右上角“创建实验”从下拉框中选择“通知实验” 填写本次A/B测试实验的名称和描述,这里我们可以将实验命名为“618节日促销推送文案测试” 进入“选择实验目标用户”页面,设置实验筛选用户和比例。我们这里选择 “所有用户”参与用户比例设置为5%,系统会从所有用户中筛选出5%的用户,并平均分配到原始组和实验组中。 在“配置原始组和实验组”页面,我们可以将两条待测试的推送文案信息填写在这里。原始组的文案为“您有5元现金红包已入账,限量可领,购物立减,手慢无”实验组的文案为“5元无门槛红包已到账,全场通用,仅限1天有效!”点击文案均跳转到首页。 在“选择跟踪指标”页面,选择本次推送想要跟踪的主要指标和次要指标。我们本次测试想看两种不同推送文案的打开率,所以我们将主要指标设置为“点击率” 在“设置消息选项”页面,可以选择推送时间、推送有效期和推送重要性。点击“保存”会进入实验报告界面,在该界面可以查看本次A/B测试的具体推送效果。 经过以上5步,我们就成功完成了一次A/B测试推送,通过查看测试结果,我们可以找出最理想的通知文案和消息呈现方式,从而提高正式推送时的打开率和转化率。 了解更多详情>> 访问华为开发者联盟官网 获取开发指导文档 华为移动服务开源仓库地址:GitHub、Gitee 关注我们,第一时间了解 HMS Core 最新技术资讯~

优秀的个人博客,低调大师

编程谜题:提升你解决问题的训练场

摘要:有趣的编程谜题可以练习你解决问题的能力,快来挑战吧~~ 本文分享自华为云社区《代码的出现:用 Python 解决你的难题》,作者: Yuchuan 。 代码谜题的出现旨在让任何对解决问题感兴趣的人都能上手。您不需要具有深厚的计算机科学背景即可参与。相反,代码的来临是学习新技能和测试 Python 新功能的绝佳场所。 编程中的困惑? 处理谜题似乎是在浪费您可用的编程时间。毕竟,您似乎并没有真正生产出任何有用的东西,也没有推进您当前的项目。 然而,花一些时间练习编程谜题有几个好处: 与您的常规工作任务相比,编程难题通常更明确且包含更多内容。它们让您有机会针对比您在日常工作中通常需要处理的问题更简单的问题练习逻辑思维。 你经常可以用几个类似的谜题来挑战自己。这使您可以建立程序记忆,就像肌肉记忆一样,并获得构建某些类型代码的经验。 拼图的设计通常着眼于解决方案。它们使您可以了解和应用经过试验和测试的算法,这些算法是任何程序员工具箱的重要组成部分。 对于一些谜题解决方案,如果算法效率低下,即使是最强大的超级计算机也可能太慢。您可以分析您的解决方案的性能并获得经验,以帮助您了解什么时候简单的方法足够快,什么时候需要更优化的程序。 大多数编程语言都非常适合解决编程难题。这为您提供了一个很好的机会,可以针对不同的任务比较不同的编程语言。拼图也是了解新编程语言或尝试您最喜欢的语言的一些最新功能的好方法。 最重要的是,用编程难​​题挑战自己通常非常有趣!当你把所有的东西加起来时,为谜题留出一些时间是非常有益的。 探索在线解决编程难题的选项 幸运的是,您可以在许多网站上找到编程难题并尝试解决它们。这些网站存在的问题类型、您提交解决方案的方式以及网站可以提供的反馈和社区类型通常存在差异。因此,您应该花一些时间环顾四周,找到对您最有吸引力的那些。 在本教程中,您将了解代码的来临,包括您可以在那里找到什么样的谜题以及您可以使用哪些工具和技巧来解决它们。但是,您也可以在其他地方开始解决编程难题: Exercism有许多不同编程语言的学习路径。每个学习轨道都提供有关不同编程概念、编码挑战和指导者的小型教程,为您提供有关解决方案的反馈。 欧拉计划已经存在很长时间了。该网站提供数百个谜题,通常以数学问题的形式表述。您可以使用任何编程语言解决问题,一旦您解决了难题,您就可以访问社区线程,在那里您可以与其他人讨论您的解决方案。 Code Wars提供了大量的编码挑战,他们称之为katas。您可以使用许多不同的编程语言通过内置编辑器和自动化测试解决难题。之后,您可以将您的解决方案与其他人的解决方案进行比较,并在论坛中讨论策略。 如果您正在寻找工作,HackerRank具有强大的功能。他们提供许多不同技能的认证,包括解决问题和 Python 编程,以及一个工作板,可让您在工作申请中展示自己的解谜技能。 还有许多其他网站可供您练习解谜技巧。在本教程的其余部分,您将重点关注 Advent of Code 必须提供的内容。 为 Code 的出现做准备:25 个圣诞节的新鲜谜题 现在是代码出现的时候了!它由Eric Wastl于 2015 年创立。从那时起,每年 12 月都会发布包含 25 个新编程谜题的新出现日历。这些年来,拼图变得越来越流行。自 2020 年以来,已有超过 170,000人至少解决了其中一个难题。 注意:传统上,降临节日历是用于在等待圣诞节期间计算降临节天数的日历。多年来,降临节日历变得更加商业化并且失去了一些与基督教的联系。 大多数降临节日历从 12 月 1 日开始,到 12 月 24 日(平安夜)或 12 月 25 日(圣诞节)结束。如今,各种降临节日历应有尽有,包括乐高日历、茶日历和化妆品日历。 在传统的降临节日历中,您每天打开一扇门以显示里面的内容。Advent of Code 模仿了这一点,让您从 12 月 1 日到 12 月 25 日每天打开一个谜题。对于您解决的每个难题,您都将获得金星,您可以保留这些星星。 在本节中,您将更加熟悉 Advent of Code 并瞥见您的第一个谜题。稍后,您将了解如何解决这些难题的详细信息,并练习自己解决一些难题。 代码谜题的出现 Advent of Code 是一个在线 Advent 日历,从 12 月 1 日到 12 月 25 日,每天都会发布一个新的谜题。每个谜题都在美国东部时间午夜可用。Advent of Code 谜题有几个典型特征: 每个谜题由两部分组成,但在您完成第一部分之前不会显示第二部分。 每完成一个部分,您将获得一颗金星 (⭐)。这意味着如果您在一年内解决所有难题,您每天可以获得两颗星和五十颗星。 每个人的谜题都是一样的,但您需要根据从 Advent of Code 网站获得的个性化输入来解决它。这意味着您对一个谜题的答案将与其他人的不同,即使您使用相同的代码来计算它。 您可以参加全球竞赛,成为第一个解决每个难题的人。然而,这里通常挤满了高技能、有竞争力的程序员。如果您将 Code of Code 用作自己的练习,或者如果您向您的朋友和同事发起小型友好竞赛,它可能会更有趣。 要了解代码出现难题的工作原理,请考虑2020 年的第一天难题: 在你离开之前,会计精灵只需要你修正你的开支报告(你的拼图输入);显然,有些事情并没有完全加起来。 具体来说,他们需要您找到总和为的两个条目,2020然后将这两个数字相乘。 每年,都会有一个非常愚蠢的背景故事将谜题联系在一起。2020 年的故事描述了您尝试离开去度过一个当之无愧的假期,因为您已经连续几年拯救了圣诞节。这个故事通常对谜题没有影响,但跟随它仍然很有趣。 在故事的情节元素之间,你会发现谜题本身。在此示例中,您要在拼图输入中查找总和为 2,020 的两个条目。在描述问题的解释之后,您通常会找到一个示例,显示您需要执行的计算: 例如,假设您的费用报告包含以下内容: 1721 979 366 299 675 1456 在这份名单中,这两个条目总和2020是1721和299。将它们相乘产生1721 * 299 = 514579,所以正确答案是514579。 该示例向您展示了此特定数字列表的答案。如果您要开始解决这个难题,现在您将开始考虑如何在任何有效数字列表中找到这两个条目。但是,在深入研究这个难题之前,您将探索如何使用 Advent of Code 站点。 如何参与代码的出现 您已经看到了代码出现难题的示例。接下来,您将了解如何提交答案。您永远不会提交任何代码来解决难题。您只需提交答案,通常是数字或文本字符串。 通常,您将按照一系列步骤来解决网站上的难题: 登录Advent of Code网站。您可以使用来自其他服务(如 GitHub、Google、Twitter 或 Reddit)的凭据来执行此操作。 阅读拼图文字并特别注意给定的例子。您应该确保您了解示例数据的解决方案。 下载拼图的个性化输入。您将需要此输入才能找到问题的唯一答案。 编写您的解决方案。这是有趣的部分,您将在本教程的其余部分获得大量练习。 在拼图页面上输入您对拼图的答案。如果您的答案是正确的,那么您将获得一颗金星,并打开谜题的第二部分。 对拼图的第二部分重复步骤 2 到 4。第二部分与第一部分类似,但它通常会增加一些需要您调整代码的扭曲。 在拼图页面上输入您的第二个答案,以获得第二颗星并完成拼图。 请记住,您不提交任何代码——只提交您的谜题答案。这意味着可以用任何编程语言解决代码难题的出现。许多人使用 Advent of Code 来练习和学习一种新的编程语言。Advent of Code 的创建者Eric Wastl在 2019 年发表了一次演讲,他谈到了参与人员的不同背景和动机等。 注意:有一个Advent of Code的排行榜。一般来说,你应该忽略这个排行榜!它仅显示在拼图打开后谁提交了前 100 个解决方案。要想跻身排行榜,您需要大量的准备、奉献精神和竞争性编程的经验。 相反,您应该查看私人排行榜。这些在您登录后可用,它们让您有机会邀请您的朋友和同事加入更轻松的社区。您可以选择基于要么得分您的私人排行榜时的困惑基础上得到解决或者干脆数量困惑的人已经解决了的。 您还可以将您在私人排行榜中的名字链接到您的GitHub帐户,这样您就可以与朋友分享您的解决方案。登录后,您可以通过单击Advent of Code 站点菜单中的设置来进行设置。 Advent of Code 完全免费使用,但您仍然可以通过几种不同的方式支持该项目: 您可以在您的社交媒体上分享有关 Advent of Code 的信息以宣传。 您可以通过参与r/adventofcode subreddit 或其他论坛来帮助他人。 您可以邀请您的朋友参加 Advent of Code,在私人排行榜上分享您的结果。 您可以向 Advent of Code捐款。如果您这样做了,那么您将在网站上的姓名旁边看到一个AoC++徽章。 在接下来的部分中,您将看到有关如何准备使用 Python 解决代码出现问题的一些建议。还有一个很棒的列表,您可以查看与 Advent of Code 相关的许多不同资源的链接,包括许多其他人的解决方案。 用 Python 解决代码的出现 Code of Code 已成为全球许多编码人员的年度亮点。2020 年,超过 170,000人提交了他们的解决方案。自 2015 年 Advent of Code 启动以来,已有超过 380,000 名程序员参与其中。他们中的许多人使用 Python 来解决难题。 那么,现在轮到你了!前往Advent of Code 网站,查看最新的谜题。然后,返回本教程获取一些提示并帮助开始使用 Python 解决代码出现难题。 拼图的剖析 在本节中,您将探索代码出现难题的典型剖析。此外,您将了解一些可用于与之交互的工具。 每个 Advent of Code 谜题都分为两部分。当您开始处理拼图时,您只会看到第一部分。一旦您提交了第一部分的正确答案,第二部分就会解锁。这通常是您在第一部分解决的问题的转折点。有时,您会发现有必要从第一部分重构您的解决方案,而有时您可以根据您已经完成的工作快速解决第二部分。 两个部分始终使用相同的拼图输入。您可以从当天的拼图页面下载拼图输入。您会在拼图说明后找到一个链接。 注意:如前所述,您的拼图输入是个性化的。这意味着如果您与其他人讨论解决方案,他们的最终答案可能与您的不同。 提交拼图解决方案所需执行的所有操作(实际解决拼图除外)都可以在 Advent of Code 网站上完成。您应该使用它来提交您的第一个解决方案,以便您熟悉流程。 稍后,您可以使用多种工具来组织 Advent of Code 设置并提高工作效率。例如,您可以使用该advent-of-code-data包下载数据。这是一个可以使用pip安装的 Python 包: $ python -m pip install advent-of-code-data 您可以使用advent-of-code-data其aocd工具在命令行上下载特定的拼图输入集。另一个有趣的可能性是在您的 Python 代码中自动下载和缓存您的个性化拼图输入: >>> >>> from aocd.models import Puzzle >>> puzzle = Puzzle(year=2020, day=1) >>> # Personal input data. Your data will be different. >>> puzzle.input_data[:20] '1753\n1858\n1860\n1978\n' 您需要在环境变量或文件中设置会话 ID,然后才能使用advent-of-code-data. 您将在文档中找到对此的解释。如果您感兴趣,还可以使用advent-of-code-data或aocd提交您的解决方案并查看您之前的答案。 作为拼图文本的一部分,您还会发现一个或多个示例,这些示例通常是根据比您的个性化输入数据更小的数据来计算的。在开始编码之前,您应该仔细阅读这些示例,并确保您了解要求您执行的操作。 您可以使用这些示例为您的代码设置测试。一种方法是在示例数据上手动运行您的解决方案并确认您得到了预期的答案。或者,您可以使用类似工具pytest来自动化该过程。 注意:测试驱动开发 (TDD)是一个在实现代码之前编写测试的过程。由于 Advent of Code 为您提供了对小示例的预期答案,因此它为您提供了自己尝试测试驱动开发的绝佳机会。 稍后当您尝试自己解决一些难题时,您将了解有关 TDD 的更多信息。 您只需使用简单的 Python 和标准库即可解决所有 Advent of Code 难题。但是,有一些软件包可以帮助您整理解决方案: advent-of-code-data 可以下载您的输入数据并提交您的解决方案。 pytest 可以自动检查示例数据上的解决方案。 parse可以用比正则表达式更简单的语法来解析字符串。 numpy 可以有效地计算数字数组。 colorama 可以在终端中为您的解决方案设置动画。 如果您创建了一个虚拟环境并安装了这些包,那么您将拥有一个非常可靠的工具箱,用于您的 Advent of Code 冒险。后来,你会看到你如何使用的例子parse,numpy和colorama解决难题。 解决方案的结构 在上一节中,您熟悉了如何阅读和理解 Advent of Code 谜题。在本节中,您将了解如何解决这些问题。在解决“代码出现”难题之前,您无需进行大量设置。 你有没有想过如何解决你之前看到的难题?回想一下,您正在查找列表中总和为 2,020 的两个数字的乘积。在继续之前,请考虑——也许可以编写代码——如何找到以下列表中哪两个条目的总和为 2,020: numbers = [1721, 979, 366, 299, 675, 1456] 以下脚本显示了解决2020 年第 1 天难题的第一部分的一种方法: 1for num1 in numbers: 2 for num2 in numbers: 3 if num1 < num2 and num1 + num2 == 2020: 4 print(num1 * num2) 嵌套for循环从列表中查找两个数字的所有组合。第 3 行的测试实际上比实际需要的稍微复杂一些:您只需要测试数字总和是否为 2,020。但是,通过添加num1应该小于的条件,num2可以避免两次找到解。 在这个例子中,一个解决方案的模样num1 = 1721和num2 = 299,但因为你可以以任何顺序添加数字,这意味着还num1 = 299和num2 = 1721形成的解决方案。通过额外检查,仅报告后一种组合。 一旦你有了这个解决方案,你就可以将你的个性化输入数据复制到numbers列表中并计算你的谜题答案。 注意:有比尝试所有可能性更有效的方法来计算这个答案。但是,从基本方法开始通常是个好主意。引用乔·阿姆斯特朗的话说: 让它工作,然后让它漂亮,然后如果你真的,真的必须,让它快。90% 的情况下,如果你让它漂亮,它已经很快了。所以真的,只是让它漂亮!(来源) —乔·阿姆斯特朗 既然你已经看到了这个谜题的有效解决方案,你能把它做得漂亮吗? 当您解决更多难题时,您可能会开始觉得将数据复制到代码中并将其重写为有效的 Python 变得很烦人。类似地,向代码中添加一些函数可为您提供更大的灵活性。例如,您可以使用它们向代码中添加测试。 Python 有许多强大的字符串解析功能。从长远来看,最好在下载时保留输入数据,让 Python 将它们解析为可用的数据结构。事实上,将代码分成两个函数通常是有益的。一个函数将解析字符串输入,另一个函数将解决这个难题。基于这些原则,你可以重写你的代码: 1# aoc202001.py 2 3import pathlib 4import sys 5 6def parse(puzzle_input): 7 """Parse input""" 8 return [int(line) for line in puzzle_input.split()] 9 10def part1(numbers): 11 """Solve part 1""" 12 for num1 in numbers: 13 for num2 in numbers: 14 if num1 < num2 and num1 + num2 == 2020: 15 return num1 * num2 16 17if __name__ == "__main__": 18 for path in sys.argv[1:]: 19 print(f"\n{path}:") 20 puzzle_input = pathlib.Path(path).read_text().strip() 21 22 numbers = parse(puzzle_input) 23 print(part1(numbers)) 在第 12 到 15 行,您将识别出您之前的解决方案。首先,您已将其包装在一个函数中。这使得以后更容易向代码中添加自动测试。您还添加了一个parse()函数,可以将字符串行转换为数字列表。 在第 20 行,您用于pathlib将文件内容作为文本读取并去除末尾的所有空白行。循环sys.argv为您提供在命令行中输入的所有文件名。 在您处理解决方案时,这些更改为您提供了更大的灵活性。假设您已将示例数据存储在名为 的文件中,example.txt并将您的个性化输入数据存储在名为input.txt. 然后,您可以通过在命令行上提供它们的名称,在其中任何一个或什至两者上运行您的解决方案: $ python aoc202001.py example.txt input.txt example.txt: 514579 input.txt: 744475 514579确实是使用示例输入数据时问题的答案。请记住,您的个性化输入数据的解决方案将与上面显示的解决方案不同。 现在是时候让 Advent of Code 网站一展身手了!转到2020 Advent of Code 日历并找到第 1 天的谜题。如果您还没有,请下载输入数据并计算谜题的解决方案。然后,在网站上输入您的解决方案并点击提交。 起始模板 正如您在上面看到的,代码谜题的出现遵循一套结构。因此,为自己创建一个模板是有意义的,您可以在开始编写解决方案时将其用作起点。您在这样的模板中到底想要多少结构是个人品味的问题。首先,您将探索一个基于您在上一节中看到的原则的模板示例: 1# aoc_template.py 2 3import pathlib 4import sys 5 6def parse(puzzle_input): 7 """Parse input""" 8 9def part1(data): 10 """Solve part 1""" 11 12def part2(data): 13 """Solve part 2""" 14 15def solve(puzzle_input): 16 """Solve the puzzle for the given input""" 17 data = parse(puzzle_input) 18 solution1 = part1(data) 19 solution2 = part2(data) 20 21 return solution1, solution2 22 23if __name__ == "__main__": 24 for path in sys.argv[1:]: 25 print(f"{path}:") 26 puzzle_input = pathlib.Path(path).read_text().strip() 27 solutions = solve(puzzle_input) 28 print("\n".join(str(solution) for solution in solutions)) 该模板具有用于解析输入以及解决谜题的两个部分的单独函数。您根本不需要触及第 15 到 27 行。他们照顾的阅读文本从输入文件,要求parse(),part1()和part2(),然后再报告解决方案控制台。 您可以创建一个类似的模板来测试您的解决方案。 注意:如前所述,示例数据对于创建测试很有用,因为它们代表具有相应解决方案的已知数据。 以下模板pytest用作测试运行程序。它的三个不同的测试,每一个功能的准备parse(),part1()以及part2(): 1# test_aoc_template.py 2 3import pathlib 4import pytest 5import aoc_template as aoc 6 7PUZZLE_DIR = pathlib.Path(__file__).parent 8 9@pytest.fixture 10def example1(): 11 puzzle_input = (PUZZLE_DIR / "example1.txt").read_text().strip() 12 return aoc.parse(puzzle_input) 13 14@pytest.fixture 15def example2(): 16 puzzle_input = (PUZZLE_DIR / "example2.txt").read_text().strip() 17 return aoc.parse(puzzle_input) 18 19@pytest.mark.skip(reason="Not implemented") 20def test_parse_example1(example1): 21 """Test that input is parsed properly""" 22 assert example1 == ... 23 24@pytest.mark.skip(reason="Not implemented") 25def test_part1_example1(example1): 26 """Test part 1 on example input""" 27 assert aoc.part1(example1) == ... 28 29@pytest.mark.skip(reason="Not implemented") 30def test_part2_example2(example2): 31 """Test part 2 on example input""" 32 assert aoc.part2(example2) == ... 你会看到,你如何使用这个模板的例子以后。在此之前,您应该注意以下几点: 如第 1 行所示,您应该pytest使用test_前缀命名您的文件。 类似地,每个测试都在一个以test_前缀命名的函数中实现。您可以在第 20、25 和 30 行看到这些示例。 您应该更改第 5 行的导入以导入您的解决方案代码。 该模板假定示例数据存储在名为example1.txt和 的文件中example2.txt。 当您准备好开始测试时,您应该删除第 19、24 和 29 行的跳过标记。 您需要...根据示例数据和相应的解决方案填写第 22、27 和 32 行的省略号 ( )。 例如,如果您要将此模板改编为上一节中 2020 年第 1 天谜题第一部分的重写解决方案,则您需要创建一个example1.txt包含以下内容的文件: 1721 979 366 299 675 1456 接下来,您将删除前两个测试的跳过标记并按如下方式实现它们: def test_parse_example1(example1): """Test that input is parsed properly""" assert example1 == [1721, 979, 366, 299, 675, 1456] def test_part1_example1(example1): """Test part 1 on example input""" assert aoc.part1(example1) == 514579 最后,您需要确保您正在导入您的解决方案。如果您使用了 filename aoc202001.py,那么您应该将第 5 行更改为 import aoc202001: 5import aoc202001 as aoc 然后,您将运行pytest以检查您的解决方案。如果您正确地实施了您的解决方案,那么您会看到如下内容: $ pytest ====================== test session starts ===================== collected 3 items test_aoc202001.py ..s [100%] ================= 2 passed, 1 skipped in 0.02s ================= 注意... 前面的两个点 ( ) s。它们代表两个通过的测试。如果测试失败,您会看到F而不是每个点,以及出现问题的详细说明。 Cookiecutter和Copier等工具可以更轻松地处理此类模板。如果您安装了 Copier,那么您可以通过运行以下命令来使用类似于您在此处看到的模板: $ copier gh:gahjelle/template-aoc-python advent_of_code 这将为advent_of_code您计算机上目录的子目录中的一个特定拼图设置模板。 解决策略 代码谜题的出现非常多样化。随着日历的推进,您将解决许多不同的问题,并发现许多解决这些问题的不同策略。 其中一些策略非常通用,可以应用于任何谜题。如果您发现自己被一个谜题卡住了,您可以尝试解决以下问题: 重新阅读说明。代码谜题的出现通常非常明确,但其中一些可能包含大量信息。确保您没有遗漏拼图的重要部分。 积极使用示例数据。确保您了解这些结果是如何实现的,并检查您的代码是否能够重现这些示例。 一些谜题可能会涉及一些。将问题分解为更小的步骤,并单独实施和测试每个步骤。 如果您的代码适用于示例数据但不适用于您的个性化输入数据,那么您可以根据您能够手动计算的数字构建其他测试用例,以查看您的代码是否涵盖所有极端情况。 如果您仍然被卡住,那么请在一些致力于代码出现的论坛上与您的朋友和其他解谜者联系,并询问他们如何解决谜题的提示。 随着您做越来越多的谜题,您将开始认识到一些反复出现的一般谜题。 一些谜题涉及文本和密码。Python 有几个强大的工具来处理文本字符串,包括许多字符串方法。要读取和解析字符串,了解正则表达式的基础知识会很有帮助。但是,您通常也可以使用第三方parse库。 例如,假设您有字符串"shiny gold bags contain 2 dark red bags."并希望从中解析相关信息。您可以使用parse及其模式语法: >>> >>> import parse >>> string = "shiny gold bags contain 2 dark red bags." >>> pattern = "{outer_color} bags contain {num:d} {inner_color} bags." >>> match = parse.search(pattern, string) >>> match.named {'outer_color': 'shiny gold', 'num': 2, 'inner_color': 'dark red'} 在后台,parse构建一个正则表达式,但您使用类似于f-strings使用的语法的更简单的语法。 在其中一些文本问题中,明确要求您使用代码和解析器,通常构建小型自定义汇编语言。解析完代码后,通常需要运行给定的程序。实际上,这意味着您构建了一个小型状态机,可以跟踪其当前状态,包括其内存的内容。 您可以使用类将状态与行为保持在一起。在 Python 中,数据类非常适合快速设置状态机。以下示例显示了一个可以处理两种不同指令的小型状态机的实现: 1from dataclasses import dataclass 2 3@dataclass 4class StateMachine: 5 memory: dict[str, int] 6 program: list[str] 7 8 def run(self): 9 """Run the program""" 10 current_line = 0 11 while current_line < len(self.program): 12 instruction = self.program[current_line] 13 14 # Set a register to a value 15 if instruction.startswith("set "): 16 register, value = instruction[4], int(instruction[6:]) 17 self.memory[register] = value 18 19 # Increase the value in a register by 1 20 elif instruction.startswith("inc "): 21 register = instruction[4] 22 self.memory[register] += 1 23 24 # Move the line pointer 25 current_line += 1 这两个指令set并inc进行分析和内处理.run()。请注意,第5 行和第 6 行的类型提示使用更新的语法,该语法仅适用于Python 3.9及更高版本。如果您使用的是旧版本的 Python,那么您可以使用 importDict和Listfromtyping代替。 要运行您的状态机,您首先使用初始内存对其进行初始化并将程序加载到机器中。接下来,您调用.run(). 程序完成后,您可以检查.memory以查看机器的新状态: >>> >>> state_machine = StateMachine( ... memory={"g": 0}, program=["set g 44", "inc g"] ... ) >>> state_machine.run() >>> state_machine.memory {'g': 45} 该程序首先设置g为 的值44,然后增加它,使其最终值为45。 一些有趣的谜题涉及网格和迷宫。如果您的网格具有固定大小,那么您可以使用NumPy来获得它的有效表示。迷宫通常有助于可视化。您可以使用Colorama直接在您的终端中绘制: import numpy as np from colorama import Cursor grid = np.array( [ [1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 1, 1, 0, 1], [1, 0, 0, 2, 1], [1, 1, 1, 1, 1], ] ) num_rows, num_cols = grid.shape for row in range(num_rows): for col in range(num_cols): symbol = " #o"[grid[row, col]] print(f"{Cursor.POS(col + 1, row + 2)}{symbol}") 此脚本显示了使用 NumPy 数组存储网格,然后使用Cursor.POSfrom Colorama 在终端中定位光标以打印出网格的示例。运行此脚本时,您将看到如下输出: ##### # # ### # # o# ##### 在运行时可视化您的代码可能很有趣,并且还可以为您提供一些很好的见解。当您在调试并且不太了解正在发生的事情时,它也可以是非常宝贵的帮助。 到目前为止,在本教程中,您已经获得了一些关于如何使用 Advent of Code 谜题的一般提示。在接下来的部分中,您将获得更明确的信息并解决早年的两个难题。 代码实践:2019 年第 1 天 您将尝试自己解决的第一个难题是2019 年第 1 天,称为火箭方程式的暴政。这是一个典型的第 1 天难题,因为该解决方案并不是很复杂。这是一个很好的练习,可以习惯 Advent of Code 的工作方式并检查您的环境是否已正确设置。 第 1 部分:拼图说明 在 2019 年的故事情节中,你将拯救被困在太阳系边缘的圣诞老人。在第一个谜题中,您正在准备发射火箭: 精灵们迅速将您装入宇宙飞船并准备发射。 在第一次 Go / No Go 民意调查中,每个 Elf 都是 Go,直到 Fuel Counter-Upper。他们还没有确定所需的燃料量。 发射给定模块所需的燃料基于其质量。具体来说,要找到模块所需的燃料,取其质量,除以 3,向下取整,然后减去 2。 示例数据如下所示: 对于质量12,除以 3 并向下取整得到4,然后减去 2 得到2。 对于质量14,除以 3 并四舍五入仍然产生4,因此所需的燃料也是2。 对于质量为1969,所需的燃料为654。 对于质量为100756,所需的燃料为33583。 您需要计算航天器的总燃料需求: Fuel Counter-Upper 需要知道总燃料需求。要找到它,请单独计算每个模块(您的拼图输入)的质量所需的燃料,然后将所有燃料值加在一起。 您的航天器上所有模块的燃料需求总和是多少? 现在是时候尝试自己解决难题了!下载您的个性化输入数据并在 Advent of Code 上检查您的解决方案可能是最有趣的,这样您就可以获得星星。但是,如果您还没有准备好登录 Advent of Code,请根据上面提供的示例数据随意解决难题。 第 1 部分:解决方案 完成拼图并获得星星后,您可以展开折叠块以查看拼图解决方案的讨论: 2019 年第 1 天的解决方案,第 1 部分显示隐藏 您现在已经解决了谜题的第一部分。但是,在进入谜题的第二部分之前,下一部分将展示如何使用之前在解决此问题时看到的模板。 第 1 部分:使用模板的解决方案 展开下面的折叠块,查看 2019 年第 1 天代码出现难题第一部分的另一个解决方案——这次使用您之前看到的模板来组织代码并简化测试: 2019 年第 1 天第 1 部分的模板化解决方案显示隐藏 您现在可以继续进行拼图的第二部分。你准备好扭转了吗? 第 2 部分:拼图说明 每个 Advent of Code 谜题都由两部分组成,只有在您解决第一部分后才会显示第二部分。第二部分始终与第一部分相关,并将使用相同的输入数据。但是,您可能经常需要重新考虑解决谜题前半部分的方法,以便考虑后半部分。 展开下面折叠的块以查看 2019 年第 1 天代码出现难题的第二部分: 2019 年第 1 天,第 2 部分显示隐藏 您将在下一部分看到第二部分的可能解决方案。但是,请先尝试自己解决难题。如果您需要开始的提示,请展开下面的框: 2019 年第 1 天的提示,第 2 部分显示隐藏 你怎么做的?你的火箭准备好发射了吗? 第 2 部分:解决方案 本节展示了如何解决第二部分,继续使用上面看到的模板: 2019 年第 1 天的解决方案,第 2 部分显示隐藏 恭喜!您现在已经解决了整个 Advent of Code 难题。您准备好迎接更具挑战性的挑战了吗? 代码实践:2020 年第 5 天 您将尝试解决的第二个难题是2020 年第 5 天的难题,称为Binary Boarding。这个谜题比前一个更具挑战性,但最终的解决方案不需要很多代码。首先查看第一部分的拼图说明。 第 1 部分:拼图说明 2020 年,您正在努力前往您当之无愧的度假胜地。在第 5 天,当麻烦接踵而至时,您将要登机: 你登上飞机却发现一个新问题:你丢了登机牌!你不确定哪个座位是你的,所有的空乘人员都忙着处理突然通过护照检查的人潮。 您编写了一个快速程序,使用手机的摄像头扫描附近的所有登机牌(您的拼图输入);也许你可以通过淘汰的过程找到你的座位。 这家航空公司使用二元空间分区来安排座位,而不是区域或组。一个座位可能被指定为FBFBBFFRLR,其中的F意思是“前”,B意思是“后”,L意思是“左”,R意思是“右”。 前 7 个字符将是F或B; 这些精确指定的一个128行上的平面(编号0通过127)。每个字母都会告诉您给定的座位位于区域的哪一半。 从整个行列表开始;第一个字母表示座位是在前面(0通过63)还是在后面(64通过127)。下一个字母表示座位位于该区域的哪一半,依此类推,直到您只剩下一排。 例如,仅考虑 的前七个字符FBFBBFFRLR: 首先考虑整个范围,行0到127. F意味着采取下半部分,保持行0通过63。 B意味着采取上半部分,保持行32通过63。 F意味着采取下半部分,保持行32通过47。 B意味着采取上半部分,保持行40通过47。 B保持行44通过47。 F保持行44通过45。 finalF保留两者中较低的,row44。 最后三个字符将是L或R; 这些精确指定的一个8列的在飞机上的座位(编号0通过7)。再次进行与上述相同的过程,这次只需要三个步骤。L表示保留下半部分,同时R表示保留上半部分。 例如,仅考虑 的最后 3 个字符FBFBBFFRLR: 首先考虑整个范围,列0到7. R意味着采取上半部分,保持列4通过7。 L意味着采取下半部分,保持列4通过5。 finalR保留两者中的较高者,column5。 因此,解码FBFBBFFRLR显示它是row 44, column5的座位。 每个座位也有一个唯一的座位 ID:将行乘以 8,然后添加列。在此示例中,座位具有 ID 44 * 8 + 5 =357。 以下是其他一些登机牌: BFFFBBFRRR:行70,列7,座位ID 567。 FFFBBBFRRR:行14,列7,座位ID 119。 BBFFBBFRLL:行102,列4,座位ID 820。 作为健全性检查,请查看您的登机牌清单。登机牌上的最高座位 ID 是多少? 这个谜题说明中有很多信息!但是,大部分内容都涉及二进制空间分区如何为该特定航空公司工作。 现在,尝试自己解决难题!请记住,如果您从正确的角度考虑,从登机牌规范到座位 ID 的转换并不像最初看起来那么复杂。如果您发现自己在该部分遇到困难,请展开下面的框以查看有关如何开始的提示。 2020 年第 5 天的提示,第 1 部分显示隐藏 完成解决方案后,请查看下一部分以了解有关该难题的讨论。 第 1 部分:解决方案 既然您已经自己试过了,您可以继续展开以下块以查看解决难题的一种方法: 2020 年第 5 天的解决方案,第 1 部分显示隐藏 是时候进入拼图的第二部分了。你能登机吗? 第 2 部分:拼图说明 准备好拼图的第二部分后,展开以下部分: 2020 年第 5 天,第 2 部分显示隐藏 花点时间研究第二部分的解决方案。 第 2 部分:解决方案 当您准备好将您的解决方案与另一个解决方案进行比较时,请打开下面的框: 2020 年第 5 天的解决方案,第 2 部分显示隐藏 恭喜!到目前为止,您已经解决了至少两个 Advent of Code 难题。幸运的是,还有数百个等着你! 点击关注,第一时间了解华为云新鲜技术~

优秀的个人博客,低调大师

Next.js 12 正式发布,速度最高提升 5 倍

Next.js 12 被官方誉为是有史以来更新幅度最大的版本,该版本带来的变化如下: 版本特性 Rust 编译器:本地刷新速度提高了约 3 倍,构建速度提高了约 5 倍; 中间件(Beta):在 Next.js 中使用代码而不是配置,实现了充分的灵活性; 支持 React 18:现在支持 Native Next.js 的 API,以及 React 18 中的 Suspense; AVIF 支持:与 WebP 相比,可减少图片体积约 20%; 本地 ES 模块支持:与标准化的模块系统保持一致; URL 导入(Alpha):从任何 URL 导入包,不需要安装或单独的构建步骤; React 服务器组件(Alpha):包括 SSR Streaming; 开发者可以通过运行 npm i next@latest 进行更新。 重大变化 在将 webpack 5 设为 Next.js 11 中的默认版本后,现在正式在 Next.js 中移除了 webpack 4; 不再需要next.config.js中的 target next/image现在使用span而不是 div作为 Wrapping 元素; Node.js 的最低版本已经从12.0.0升级至12.22.0,这是第一个原生支持 ES 模块的 Node.js 版本; 其他改进 将 pages/_app.js 或 pages/_document.js 添加到你的应用程序,现在会自动替换内置版本,而不需要重新启动 Next.js CLI; ESLint 集成现在支持在 Next lint 中使用 --file 标志进行单文件检查; Next.js 12 现在支持设置自定义 tsconfig.json 路径; next.config.mjs 现在支持将配置写成 ES 模块; 对静态页面的检查现在使用共享工作池运行; 快速刷新现在使用 WebSocket 连接而不是 EventSource 连接; …… 更多详情可查看:https://nextjs.org/blog/next-12

优秀的个人博客,低调大师

AMD发布Windows 11芯片组驱动更新提升明显

随着3.10.08.506芯片组驱动的发布,AMD终于给锐龙CPU打上了运行Windows11 操作系统的性能补丁。此前由于协处理器无法为程序正确调用最佳性能的内核(CPPC机制),某些多线程优化不佳的应用程序会受到较大的影响。此外Windows11 首发时还遇到了锐龙CPU的L3缓存延迟异常,这点还得看微软的后续补丁优化。 AMD在芯片组驱动程序的发行说明中写道,该3.10.08.506版本已经修复了锐龙处理器在 Windows 11Build 22000.189 及以上平台的一个性能问题,恢复了UEFICPPC2(首选核心)的预期功能和行为。 具体说来是,新驱动引入了7.0.3.5版本的锐龙电源管理计划,其中包含了针对Windows11 操作系统的专属优化,以修复CPPC2方面的性能调度问题。 需要注意的是,由于Windows11 官方最低指定了AMD锐龙2000系列(以及英特尔 8代酷睿)CPU,所以新版驱动程序也仅与基于Zen+(及以上)的AMD锐龙CPU兼容。

优秀的个人博客,低调大师

Chrome OS 94 发布,内置文档扫描、提升语音质量

Google 近日发布了 Chrome OS 94 稳定版,为 Chromebook 用户带来了一些新功能。该版本发布后,Google 将跳过 Chrome OS 95 版本,目前公布的时间表显示 Google 将在 11 月 30 日直接推出 Chrome OS 96。 Chrome OS 94 的变化包括: 屏幕录制质量更好 Chrome OS 设备的内置屏幕录制功能现在能够以更高的分辨率和质量进行录制。 更好的语音质量 Google 为 「Select to Speak」功能进行了更新,更新后在朗读选定区块中的文本时,提高了语音的质量和真实性。对于那些依赖无障碍功能的人来而言,能够获得更好的体验。 内置相机应用中的文档扫描 Chrome OS 94 首次为内置的相机应用提供了文档扫描功能。用户可以使用相机扫描文件、裁剪不必要的背景,并将文件保存为 PDF 格式。 其他的变化 通话降噪默认启用:该功能自 Chrome OS 92 上首次亮相,现在将默认开启。Chrome OS 94 会自动消除用户在视频通话和会议中的噪声,获得更好的通话体验。 当执行移动标签到另一个窗口的操作时,会显示桌面标签,并对一个桌面的窗口进行分组。 更多详情可查看:https://support.google.com/chromebook/thread/130864585/introducing-chrome-os-m94-to-the-stable-channel?hl=en

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册