OCR Numbers
1. Readme
OCR 号码
给定一个 3 x 4 ,由竖线符号,下划线和空格组成的网格,确定代表哪个数字,或者是否是乱码。
第一步
首先,将简单的二进制字体,转换为包含 0 或 1 的字符串。
二进制字体使用竖线符号和下划线,四行高,三列宽.
_ #
| | # zero.
|_| #
# 第 4 行总空着
转换为”0”
#
| # one.
| #
# (4行空)
转换为”1”
如果输入的大小正确,但无法识别,则程序应返回”?”
如果输入的大小不正确,程序应该返回错误。
第二步
更新您的程序以识别多二进制字符串,用 ? 替换乱码。
第三步
更新程序,以识别所有数字 0 到 9,既可以单独识别,也可以作为更大字符串的一部分识别。
_
_|
|_
转换为”2”
_ _ _ _ _ _ _ _ #
| _| _||_||_ |_ ||_||_|| | # 十进制数.
||_ _| | _||_| ||_| _||_| #
# 第 4 行空着
被转换为”1234567890”
第四步
更新程序以处理多个数字,每 4 行。转换多行时,请使用逗号连接行.
_ _
| _| _|
||_ _|
_ _
|_||_ |_
| _||_|
_ _ _
||_||_|
||_| _|
被转换为”123,456,789”
资源
灵感来自银行 OCR katahttp://codingdojo.org/cgi-bin/wiki.pl?KataBankOCR
2. 开始你的表演
// The code below is a stub. Just enough to satisfy the compiler. // In order to pass the tests you can add-to or change any of this code. #[derive(Debug, PartialEq)] pub enum Error { InvalidRowCount(usize), InvalidColumnCount(usize), } pub fn convert(input: &str) -> Result<String, Error> { unimplemented!("Convert the input '{}' to a string", input); }
3. 测试代码查看
# #![allow(unused_variables)] #fn main() { #[test] #[cfg_attr(rustfmt, rustfmt_skip)] fn input_with_lines_not_multiple_of_four_is_error() { let input = " _ \n".to_string() + "| |\n" + " "; assert_eq!(Err(Error::InvalidRowCount(3)), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn input_with_columns_not_multiple_of_three_is_error() { let input = " \n".to_string() + " |\n" + " |\n" + " "; assert_eq!(Err(Error::InvalidColumnCount(4)), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn unrecognized_characters_return_question_mark() { let input = " \n".to_string() + " _\n" + " |\n" + " "; assert_eq!(Ok("?".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_0() { let input = " _ \n".to_string() + "| |\n" + "|_|\n" + " "; assert_eq!(Ok("0".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_1() { let input = " \n".to_string() + " |\n" + " |\n" + " "; assert_eq!(Ok("1".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_2() { let input = " _ \n".to_string() + " _|\n" + "|_ \n" + " "; assert_eq!(Ok("2".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_3() { let input = " _ \n".to_string() + " _|\n" + " _|\n" + " "; assert_eq!(Ok("3".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_4() { let input = " \n".to_string() + "|_|\n" + " |\n" + " "; assert_eq!(Ok("4".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_5() { let input = " _ \n".to_string() + "|_ \n" + " _|\n" + " "; assert_eq!(Ok("5".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_6() { let input = " _ \n".to_string() + "|_ \n" + "|_|\n" + " "; assert_eq!(Ok("6".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_7() { let input = " _ \n".to_string() + " |\n" + " |\n" + " "; assert_eq!(Ok("7".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_8() { let input = " _ \n".to_string() + "|_|\n" + "|_|\n" + " "; assert_eq!(Ok("8".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_9() { let input = " _ \n".to_string() + "|_|\n" + " _|\n" + " "; assert_eq!(Ok("9".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_110101100() { let input = " _ _ _ _ \n".to_string() + " | || | || | | || || |\n" + " | ||_| ||_| | ||_||_|\n" + " "; assert_eq!(Ok("110101100".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn replaces_only_garbled_numbers_with_question_mark() { let input = " _ _ _ \n".to_string() + " | || | || | || || |\n" + " | | _| ||_| | ||_||_|\n" + " "; assert_eq!(Ok("11?10?1?0".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn recognizes_string_of_decimal_numbers() { let input = " _ _ _ _ _ _ _ _ \n".to_string() + " | _| _||_||_ |_ ||_||_|| |\n" + " ||_ _| | _||_| ||_| _||_|\n" + " "; assert_eq!(Ok("1234567890".to_string()), convert(&input)); } #[test] //#[ignore] #[cfg_attr(rustfmt, rustfmt_skip)] fn numbers_across_multiple_lines_are_joined_by_commas() { let input = " _ _ \n".to_string() + " | _| _|\n" + " ||_ _|\n" + " \n" + " _ _ \n" + "|_||_ |_ \n" + " | _||_|\n" + " \n" + " _ _ _ \n" + " ||_||_|\n" + " ||_| _|\n" + " "; assert_eq!(Ok("123,456,789".to_string()), convert(&input)); } #}
4. 答案
# #![allow(unused_variables)] #fn main() { use std::collections::BTreeMap; #[derive(Debug, PartialEq)] pub enum Error { InvalidRowCount(usize), InvalidColumnCount(usize), } pub fn convert(input: &str) -> Result<String, Error> { let line_count = input.lines().count(); if line_count % 4 != 0 { return Err(Error::InvalidRowCount(line_count)); } for line in input.lines() { let char_count = line.chars().count(); if char_count % 3 != 0 { return Err(Error::InvalidColumnCount(char_count)); } } let y = input.lines().collect::<Vec<_>>(); let mut converted_lines = vec![]; for char_lines in y.chunks(4) { let mut unparsed_characters = BTreeMap::new(); for line in char_lines { let line_chars = line.chars().collect::<Vec<_>>(); for (char_number, char_chunk) in line_chars.chunks(3).enumerate() { let char_chars = unparsed_characters.entry(char_number).or_insert(vec![]); for c in char_chunk { char_chars.push(*c); } } } let mut parsed_characters = String::new(); for (_, v) in unparsed_characters { parsed_characters.push(convert_character(&v)); } converted_lines.push(parsed_characters.to_string()); } Ok(converted_lines.join(",")) } fn convert_character(input: &Vec<char>) -> char { if &input[..] == [' ', '_', ' ', '|', ' ', '|', '|', '_', '|', ' ', ' ', ' '] { '0' } else if &input[..] == [' ', ' ', ' ', ' ', ' ', '|', ' ', ' ', '|', ' ', ' ', ' '] { '1' } else if &input[..] == [' ', '_', ' ', ' ', '_', '|', '|', '_', ' ', ' ', ' ', ' '] { '2' } else if &input[..] == [' ', '_', ' ', ' ', '_', '|', ' ', '_', '|', ' ', ' ', ' '] { '3' } else if &input[..] == [' ', ' ', ' ', '|', '_', '|', ' ', ' ', '|', ' ', ' ', ' '] { '4' } else if &input[..] == [' ', '_', ' ', '|', '_', ' ', ' ', '_', '|', ' ', ' ', ' '] { '5' } else if &input[..] == [' ', '_', ' ', '|', '_', ' ', '|', '_', '|', ' ', ' ', ' '] { '6' } else if &input[..] == [' ', '_', ' ', ' ', ' ', '|', ' ', ' ', '|', ' ', ' ', ' '] { '7' } else if &input[..] == [' ', '_', ' ', '|', '_', '|', '|', '_', '|', ' ', ' ', ' '] { '8' } else if &input[..] == [' ', '_', ' ', '|', '_', '|', ' ', '_', '|', ' ', ' ', ' '] { '9' } else { '?' } } #}