云服务通用表格识别图片转换
云服务通用表格识别图片转换
1. 题目
今天学习1105专业级第二题。题目:
题目描述 华为云推出了“通用表格识别”服务,可以将图片表格转换成文本数据。请你把文本数据进一步转换为「文本型表格」, 如下图所示:
现给出一个图片表格的文本数据: · 每行数据形如 line3 col1 A,表示第3行第1列的单元格的内容为 A · 表格的行和列都从 1 开始;文本数据中行、列的最大值分别为表格的行、列数。 · 内容为由英文字符A-Z组成的字符串,或为空;未描述的单元格内容为空。 请按如下格式要求,将文本数据转换成「文本型表格」: · 表格第一行和最后一行用字母+和字母-组成,+代表单元格的间隔,-代表一个字符的占位符; · 数据行: · 用字符|标识单元格的左右边界。 · 某一列的宽度是该列中所有单元格最长内容长度 + 2(即左右各补充 1个空格),该列中内容不足该宽度的用空格补充。 · 表格中单元格的内容要求居中对齐,对齐要求: 输入 第一行一个整数 num,表示文本数据的行数,范围 [1,20]。 · line 是行的固定前缀,行取值范围 [1,100] · col 是列的固定前缀,列取值范围 [1,100] · 内容为仅由英文字符A-Z组成的字符串,或为空,长度范围 [0,10]。 输出 字符串表示的「文本型表格」 样例 输入样例 1 8 line1 col3 CN line1 col1 A line1 col4 D line3 col1 X line2 col1 line2 col2 BE line2 col3 LMN line2 col4 输出样例 1 +---+----+-----+---+ | A | | CN | D | | | BE | LMN | | | X | | | | +---+----+-----+---+ 提示样例 1 表格的行列数: 表格的各列宽度: · 第1列:内容最长为1,加2,该列宽度为3 。 · 第2列:内容最长为2,加2,该列宽度为4 。 · 第3列:内容最长为3,加2,该列宽度为5 。该列中内容LMN最长,左右各补充一个空格;CN左侧补充一个空格,右侧补充两个空格。 · 第4列:内容最长为1,加2,该列宽度为3 。 输入样例 2 2 line2 col2 A line2 col3 输出样例 2 +--+---+--+ | | | | | | A | | +--+---+--+ 提示样例 2 · 从输入得到数据的行列数分别为2和3;第一行、第一列、第三列即使内容为空,也需要输出。 其中第一列内容都为空,列宽度为2(该列中所有单元格最长内容长度 +2)。
|
2. 题目分析
题目理解:
题目给出一个表格的文字描述作为输入,要求按照指定格式打印输出表格。
需要完成的处理有:
l 解析每一行字符串,得到每个单元格的文本内容
l 因为输入没有直接给出最大行数和列数,所以需要解析得到最大的行数、列数
l 得到每一列的最大宽度
注意点:
l 某一列的宽度是该列中所有单元格最长内容长度 + 2,当整列的单元格都是空的时候,最长内容长度是2
l 单元格内要求居中对齐,如左右两个空格无法相等,则靠左、右边多一个空格
l 输入未描述的单元格文本为空
解题思路:
可以分为两大步骤:
l 构造数据:解析输入字符串,得到所有单元格的文本,同时记录每一列的最大宽度
由于行和列的最大取值是100、每个单元格内的字符串长度最多10,所以可以直接用数组来存储表格内容和每列列宽。
如果数据规模很大(例如超过100万),就要考虑用hash来存储了。
在记录列宽时,直接用len(单元格文本)+2,不用再加上边框字符所占的宽度。
l 显示数据:逐行打印输出每个单元格
打印输出时通常有两种做法:
l 做法1:先填充到数组中,再print整个数组
l 做法2:直接print每一行
居中对齐时,用下面这个计算方法是比较简便的:
int leftFill = (colLen[i] - stringLen) / 2; // 左边要填充的空格数
int rightFill = colLen[i] - stringLen - leftFill; // 右边要填充的空格数
以样例1的第1行第3列为例:“| CN |”,leftFill=(5-2)/2=1,rightFill=5-2-1=2
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. * Description: 上机编程认证 * Note: 缺省代码仅供参考,可自行决定使用、修改或删除 * 只能import Go标准库 */ package main import ( "bufio" "fmt" "io" "os" "strconv" "strings" ) // 待实现函数,在此函数中填入答题代码 type element struct { line int col int content string } const ( minInputNum = 2 lineIndex = 0 colIndex = 1 contentIndex = 2 twoSpace = 2 maxInputCol = 100 maxContentLen = 10 ) func splitString(input string) *element { var element element str := strings.Split(input, " ") if len(str) < minInputNum { return nil } lineStr := strings.TrimLeft(str[lineIndex], "line") line, err := strconv.Atoi(strings.TrimSpace(lineStr)) if err != nil || line < 1 || line > maxInputCol { return nil } colStr := strings.TrimLeft(str[colIndex], "col") col, err := strconv.Atoi(strings.TrimSpace(colStr)) if err != nil || col < 1 || col > maxInputCol { return nil } element.line = line element.col = col if len(str) > minInputNum { element.content = strings.TrimSpace(str[contentIndex]) } if len(element.content) > maxContentLen { return nil } return &element } func initLineString(contentLenArr []int, maxCol int) string { str := "|" i := 0 for i < maxCol { j := 0 for j < contentLenArr[i]+twoSpace { str += " " j++ } str += "|" i++ } return str } func initResultString(contentLenArr []int, maxLine int, maxCol int) []string { result := make([]string, 0, maxLine+twoSpace) firstLine := "+" i := 0 for i < maxCol { j := 0 for j < contentLenArr[i]+twoSpace { firstLine += "-" j++ } firstLine += "+" i++ } result = append(result, firstLine) i = 0 for i < maxLine { str := initLineString(contentLenArr, maxCol) result = append(result, str) i++ } result = append(result, firstLine) return result } func createLineString(element *element, lineStr string, contentLenArr []int) string { contentNum := len(element.content) if contentNum == 0 { return lineStr } startChar := 0 i := 0 for i < element.col-1 { startChar = startChar + (contentLenArr[i] + twoSpace + 1) i++ } startChar = startChar + twoSpace + (contentLenArr[element.col-1]-contentNum)/twoSpace result := []byte(lineStr) j := 0 for j < len(element.content) { result[startChar] = element.content[j] startChar++ j++ } return string(result) } func createResultString(elements []*element, contentLenArr []int, maxLine int, maxCol int) []string { result := initResultString(contentLenArr, maxLine, maxCol) num := len(elements) i := 0 for i < num { lineString := createLineString(elements[i], result[elements[i].line], contentLenArr) result[elements[i].line] = lineString i++ } return result } func transformationTable(tableInfo []string) []string { num := len(tableInfo) maxLine := 0 maxCol := 0 elementArray := make([]*element, 0, num) contentLenArr := make([]int, maxInputCol) i := 0 for i < num { element := splitString(tableInfo[i]) if element == nil { return nil } if element.line > maxLine { maxLine = element.line } if element.col > maxCol { maxCol = element.col } if len(element.content) > contentLenArr[element.col-1] { contentLenArr[element.col-1] = len(element.content) } elementArray = append(elementArray, element) i++ } return createResultString(elementArray, contentLenArr, maxLine, maxCol) } func main() { reader := bufio.NewReader(os.Stdin) var line int if _, err := fmt.Fscanf(reader, "%d\n", &line); err != nil { return } tableInfo, err := readInputStrArrayFromNlines(reader, line) if err != nil { return } result := transformationTable(tableInfo) for _, value := range result { fmt.Println(value) } } func readInputStrArrayFromNlines(reader *bufio.Reader, num int) ([]string, error) { if num <= 0 { return []string{}, nil } result := make([]string, 0, num) for i := 0; i < num; i++ { lineBuf, err := reader.ReadString('\n') if err != nil && err != io.EOF { return nil, err } lineBuf = strings.TrimRight(lineBuf, "\r\n") lineBuf = strings.TrimSpace(lineBuf) result = append(result, lineBuf) } return result, nil }
题目二: 日志记录,树,递归
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * Copyright (c) Huawei Technologies Co., Ltd. 2019-2022. All rights reserved. * Description: 上机编程认证 * Note: 缺省代码仅供参考,可自行决定使用、修改或删除 * 只能import Go标准库 * 2 12:00|test1|1|Create 2 13:00|test2|2|Create 9 1 */ package main import ( "bufio" "fmt" "io" "os" "strconv" "strings" ) func ConvertIntSlice2Map(rootIds []int) map[int]struct{} { set := make(map[int]struct{}, len(rootIds)) for _, rootId := range rootIds { set[rootId] = struct{}{} } return set } func DeleteStrSlice(messages []string, elem string) []string { tmp := make([]string, 0, len(messages)) for _, message := range messages { if message != elem { tmp = append(tmp, message) } } return tmp } func DeleteIntSlice(rootIds []int, elem int) []int { tmp := make([]int, 0, len(rootIds)) for _, rootId := range rootIds { if rootId != elem { tmp = append(tmp, rootId) } } return tmp } var treeList [][]int func getDepthTreeList(processIds []int, messages []string) [][]int { rootIds := make([]int, 0) if len(processIds) == 0 { return [][]int{} } var messageList string for messageKey := range messages { messageList += messages[messageKey] } for _, processId := range processIds { processIdStr := strconv.Itoa(processId) if !strings.Contains(messageList, processIdStr) { rootIds = append(rootIds, processId) } } treeList = append(treeList, rootIds) mapStructIdList := ConvertIntSlice2Map(processIds) // 去掉已经获取到的root节点 for _, rootId := range rootIds { if _, ok := mapStructIdList[rootId]; ok { processIds = DeleteIntSlice(processIds, rootId) } } for _, processId := range processIds { processIdStr := strconv.Itoa(processId) for i := 0; i < len(messages); i++ { if strings.Contains(messages[i], processIdStr) { messages = DeleteStrSlice(messages, messages[i]) } } } getDepthTreeList(processIds, messages) return treeList } func getLastDepth(depth int) int { res := 0 for i := 0; i < len(treeList); i++ { if i == (depth - 1) { res = len(treeList[i]) } } return res } // 待实现函数,在此函数中填入答题代码 func logOutput(logs []string, depth int) int { // 先构造树 messages := make([]string, 0) processIds := make([]int, 0) for _, log := range logs { logLists := strings.Split(log, "|") processId, err := strconv.Atoi(logLists[2]) if err != nil { return 0 } processIds = append(processIds, processId) messages = append(messages, logLists[3]) } treeList = getDepthTreeList(processIds, messages) // 统计深度为depth的总数 ans := getLastDepth(depth) return ans } func main() { reader := bufio.NewReader(os.Stdin) logs := readInputStrArrayFromNlines(reader) depth := readInputInt(reader) result := logOutput(logs, depth) fmt.Println(result) } func readInputStrArrayFromNlines(reader *bufio.Reader) []string { var line int if _, err := fmt.Fscanf(reader, "%d\n", &line); err != nil { fmt.Println(err.Error()) return nil } result := make([]string, 0, line) for i := 0; i < line; i++ { lineBuf, err := reader.ReadString('\n') if err != nil && err != io.EOF { fmt.Println(err.Error()) return nil } lineBuf = strings.TrimRight(lineBuf, "\r\n") lineBuf = strings.TrimSpace(lineBuf) result = append(result, lineBuf) } return result } func readInputInt(reader *bufio.Reader) int { var num int if _, err := fmt.Fscanf(reader, "%d\n", &num); err != nil { fmt.Println(err.Error()) return 0 } return num }
本文来自博客园,作者:易先讯,转载请注明原文链接:https://www.cnblogs.com/gongxianjin/p/17206240.html