识别被挤压的数字图像(蛮有趣)
2008-02-24 21:18
183 查看
给定一个仅包括加法运算的算式,请计算出结果。
算式以类似下面的形式给出:
@ @@@ @@@ @ @ @@@ @ @@@ @@@ @@@ @@@ @@@
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @
@ @@@ @@@ @@@ @@@ @@@ @@@ @ @@@ @@@ @ @
@ @ @ @ @ @ @ @ @ @ @ @ @ @
@ @@@ @@@ @ @@@ @ @@@ @ @@@ @@@ @@@
数字和+号的位置大小比例以及笔画长短粗细间距都是可变的。例如上面的算式也可以是这样:
@@@@
@@ @@@ @@@@ @@@ @@@ @@@ @@@ @@@@@
@@ @@@ @@ @ @@@ @ @ @ @ @ @@@@@
@@ @ @@@@ @ @ @ @ @ @ @ @ @ @ @@ @@
@@ @@@ @@@@ @@@ @@@ @@@ @@@ @ @@@ @@@ @@@@@
@@ @ @@ @ @ @ @ @ @ @ @ @ @@@@@
@@ @@@ @@@@ @ @@@ @ @@@ @ @@@ @@@
@@@@ @
@
但是保证不会发生笔画的缺损断裂歪斜扭曲等情况,所有字符在外形上都是可以辨识的,不会与其他字符发生混淆。相邻两个字符之间至少使用一列空格符分隔。
输入文件expression.in中包含了一个算式,文件总行数不超过100,每行不超过100个字符。运算的最终结果不超过10000000。算式只由@组成。
在expression.out中输出单独一行一个整数表示最终的运算结果。
输入样例:
@
@ @
@@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @ @@@@@@@@@@@@@@@@ @@@
@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @ @ @
@@@@@@@@@@@@@@ @ @@@ @
@ @
@@@
@
@@@
输出样例:33
上面是挤压的:7+11+15
这题思想不难,写起来有点烦~~过程如下
1.先通过一次扫描将每个数字的下标和所占的宽度记录到sign[]数组中
2.然后依次横向压缩放入compressStr1
3.再将comperessStr1纵向压缩放入comperssStr2
这里的压缩就是如果上一行(列)与下一行相同则取出上一行(列)
-------b.txt--
@
@ @
@@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @ @@@@@@@@@@@@@@@@ @@@
@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @ @ @
@@@@@@@@@@@@@@ @ @@@ @
@ @
@@@
@
@@@
--------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication2
{
//记录分割的起始地址下标和宽度
class Sign
{
public int idx = 0;
public int len = 0;
public Sign(int i, int l)
{
idx = i; len = l;
}
}
class Program
{
int adjust()
{
//结束施放
using (
StreamReader sr = new StreamReader(new FileStream(Environment.CurrentDirectory + "//b.txt"
, FileMode.Open, FileAccess.Read)))
{
//存储算式
string[] str1 = new string[100];
//行数
int maxRows = 0;
int maxCols=0;
//载入
while (!sr.EndOfStream)
{
str1[maxRows++] = sr.ReadLine();
}
//打印
print(str1,maxRows);
int tmp=0;
//获取maxCols的值
for (int row = 0; row < maxRows; row++)
{
tmp = str1[row].Length;
if (maxCols < tmp)
maxCols = tmp;
}
//该列的空格数
int[] spaceCount=new int[maxCols];
//找到全空列
for (int row = 0; row < maxRows; row++)
{
for (int col = 0; col <str1[row].Length ; col++)
{
//出现@则修改spacCount
if (str1[row][col].ToString() == "@")
spaceCount[col]=1;
}
}
//分割的下标位置
int[] partitionIndex = new int[maxCols/2];
//精确标识下标及其长度
List<Sign> signIndex = new List<Sign>();
//获取不空列的下标
int pIdx = 0;
//取出所有字符所有在列的下标及其长度 singIndex
for(int col=0;col<maxCols;col++)
{
//当前列是有数字的的
if (spaceCount[col] == 1)
{
//连续len++
if (pIdx > 0 && (signIndex[signIndex.Count-1].idx == col -
signIndex[signIndex.Count-1].len))
{
signIndex[signIndex.Count - 1].len++;
}
else
{
signIndex.Add(new Sign(col, 1));
}
pIdx++;
}
}
//总字符数
int maxLetter = signIndex.Count;
//StringBuilder curSb = new StringBuilder();
//被压缩的字符
List<string>[] compressStr = new List<string>[maxLetter];
for (int idx = 0; idx < maxLetter;idx++ )
{
compressStr[idx] = new List<string>();
}
//逐个纵向字母压缩
for (int letter = 0; letter < maxLetter; letter++)//行扫描
{
//行数
for (int row = 0; row < maxRows; row++)
{
StringBuilder curRowSb = new StringBuilder();
//获取当前 当前row 中的字符串
for (int col = signIndex[letter].idx; col < signIndex[letter].idx+signIndex[letter].len;
col++)
{
if (col >= str1[row].Length)
{
curRowSb.Append(" ");
}
else
curRowSb.Append(str1[row][col]);
}
string emptys = EmptyString(signIndex[letter].len);
//空 或者与上一行相等
//压缩
if (curRowSb.ToString() == emptys || (compressStr[letter].Count > 0
&& compressStr[letter][compressStr[letter].Count - 1] == curRowSb.ToString()))
{
continue;//next row
}
else
{
compressStr[letter].Add(curRowSb.ToString());
}
//清空
curRowSb = null;
}
}
//第二次压缩
List<string>[] compressStr2 = new List<string>[maxLetter];
for (int idx = 0; idx < maxLetter; idx++)
{
compressStr2[idx] = new List<string>();
}
//横向压缩
for (int letter = 0; letter < maxLetter; letter++)
{
for (int col = 0; col < signIndex[letter].len; col++)
{
StringBuilder comp1ColSb = new StringBuilder();
for (int row=0;row<compressStr[letter].Count; row++)
{
if(col<compressStr[letter][row].Length)
comp1ColSb.Append(compressStr[letter][row][col]);
else
comp1ColSb.Append(" ");
}
//已经加到
StringBuilder comp2ColSb = new StringBuilder();
//压缩
if (compressStr2[letter].Count > 0 )
{
//获取letter的col列
for (int row = 0; row < compressStr2[letter].Count; row++)
{
comp2ColSb.Append(compressStr2[letter][row][compressStr2[letter][row].Length-1]);
}
//相等列
if (comp1ColSb.ToString() == comp2ColSb.ToString())
continue;
else//插入列
{
//count 为行数
for (int row = 0; row < compressStr2[letter].Count; row++)
{
//c2ColSb为当前列
compressStr2[letter][row] += comp1ColSb[row].ToString();
}
}
}
else
{
//建立rows
for (int row = 0; row < comp1ColSb.Length; row++)
{
//c2ColSb为当前列
compressStr2[letter].Add(comp1ColSb[row].ToString());
}
}
}
}
//运算
return compute(compressStr2);
}
}
//计算算式
int compute(List<string>[] cps)
{
StringBuilder cti = new StringBuilder();
for (int i = 0; i < cps.Length; i++)
{
StringBuilder sb = new StringBuilder();
for (int j = 0; j < cps[i].Count; j++)
{
sb.Append(cps[i][j]);
}
cti.Append(changetoint(sb.ToString()));
}
//下标
int index=0;
//结果
int tSum=0,resultSum=0;
//存取数
int tp=0;
while(index<cti.Length)
{
tSum = 0;
while(index<cti.Length&& int.TryParse(cti[index++].ToString(),out tp))
{
tSum = tSum * 10 + tp;
}
resultSum+=tSum;
}
return resultSum;
}
//将图像变成数字
char changetoint(string s)
{
switch (s)
{
case "@": return '1';
case "@@@ @@@@@ @@@": return '2';
case "@@ @@@ @@@": return '3';
case "@ @@@@ @": return '4';
case "@@@@ @@@ @@@@": return '5';
case "@@@@ @@@@ @@@@":return '6';
case "@@ @": return '7';
case "@@@@ @@@@@ @@@@": return '8';
case "@@@@ @@@@ @@@@": return '9';
case "@@@@ @@@@": return '0';
default: return '+';
}
}
string EmptyString(int n)
{
StringBuilder sb = new StringBuilder();
while (n-- > 0)
{
sb.Append(" ");
}
return sb.ToString();
}
void print(string[] str, int idx)
{
for(int i=0;i<idx;i++)
{
Console.WriteLine(str[i]);
}
}
static void Main(string[] args)
{
Program p = new Program();
Console.Write(p.adjust().ToString());
Console.ReadLine();
}
}
}
算式以类似下面的形式给出:
@ @@@ @@@ @ @ @@@ @ @@@ @@@ @@@ @@@ @@@
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @
@ @@@ @@@ @@@ @@@ @@@ @@@ @ @@@ @@@ @ @
@ @ @ @ @ @ @ @ @ @ @ @ @ @
@ @@@ @@@ @ @@@ @ @@@ @ @@@ @@@ @@@
数字和+号的位置大小比例以及笔画长短粗细间距都是可变的。例如上面的算式也可以是这样:
@@@@
@@ @@@ @@@@ @@@ @@@ @@@ @@@ @@@@@
@@ @@@ @@ @ @@@ @ @ @ @ @ @@@@@
@@ @ @@@@ @ @ @ @ @ @ @ @ @ @ @@ @@
@@ @@@ @@@@ @@@ @@@ @@@ @@@ @ @@@ @@@ @@@@@
@@ @ @@ @ @ @ @ @ @ @ @ @ @@@@@
@@ @@@ @@@@ @ @@@ @ @@@ @ @@@ @@@
@@@@ @
@
但是保证不会发生笔画的缺损断裂歪斜扭曲等情况,所有字符在外形上都是可以辨识的,不会与其他字符发生混淆。相邻两个字符之间至少使用一列空格符分隔。
输入文件expression.in中包含了一个算式,文件总行数不超过100,每行不超过100个字符。运算的最终结果不超过10000000。算式只由@组成。
在expression.out中输出单独一行一个整数表示最终的运算结果。
输入样例:
@
@ @
@@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @ @@@@@@@@@@@@@@@@ @@@
@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @ @ @
@@@@@@@@@@@@@@ @ @@@ @
@ @
@@@
@
@@@
输出样例:33
上面是挤压的:7+11+15
这题思想不难,写起来有点烦~~过程如下
1.先通过一次扫描将每个数字的下标和所占的宽度记录到sign[]数组中
2.然后依次横向压缩放入compressStr1
3.再将comperessStr1纵向压缩放入comperssStr2
这里的压缩就是如果上一行(列)与下一行相同则取出上一行(列)
-------b.txt--
@
@ @
@@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @ @@@@@@@@@@@@@@@@ @@@
@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ @
@@@@@@@@@@@@@@@ @ @ @
@@@@@@@@@@@@@@ @ @@@ @
@ @
@@@
@
@@@
--------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication2
{
//记录分割的起始地址下标和宽度
class Sign
{
public int idx = 0;
public int len = 0;
public Sign(int i, int l)
{
idx = i; len = l;
}
}
class Program
{
int adjust()
{
//结束施放
using (
StreamReader sr = new StreamReader(new FileStream(Environment.CurrentDirectory + "//b.txt"
, FileMode.Open, FileAccess.Read)))
{
//存储算式
string[] str1 = new string[100];
//行数
int maxRows = 0;
int maxCols=0;
//载入
while (!sr.EndOfStream)
{
str1[maxRows++] = sr.ReadLine();
}
//打印
print(str1,maxRows);
int tmp=0;
//获取maxCols的值
for (int row = 0; row < maxRows; row++)
{
tmp = str1[row].Length;
if (maxCols < tmp)
maxCols = tmp;
}
//该列的空格数
int[] spaceCount=new int[maxCols];
//找到全空列
for (int row = 0; row < maxRows; row++)
{
for (int col = 0; col <str1[row].Length ; col++)
{
//出现@则修改spacCount
if (str1[row][col].ToString() == "@")
spaceCount[col]=1;
}
}
//分割的下标位置
int[] partitionIndex = new int[maxCols/2];
//精确标识下标及其长度
List<Sign> signIndex = new List<Sign>();
//获取不空列的下标
int pIdx = 0;
//取出所有字符所有在列的下标及其长度 singIndex
for(int col=0;col<maxCols;col++)
{
//当前列是有数字的的
if (spaceCount[col] == 1)
{
//连续len++
if (pIdx > 0 && (signIndex[signIndex.Count-1].idx == col -
signIndex[signIndex.Count-1].len))
{
signIndex[signIndex.Count - 1].len++;
}
else
{
signIndex.Add(new Sign(col, 1));
}
pIdx++;
}
}
//总字符数
int maxLetter = signIndex.Count;
//StringBuilder curSb = new StringBuilder();
//被压缩的字符
List<string>[] compressStr = new List<string>[maxLetter];
for (int idx = 0; idx < maxLetter;idx++ )
{
compressStr[idx] = new List<string>();
}
//逐个纵向字母压缩
for (int letter = 0; letter < maxLetter; letter++)//行扫描
{
//行数
for (int row = 0; row < maxRows; row++)
{
StringBuilder curRowSb = new StringBuilder();
//获取当前 当前row 中的字符串
for (int col = signIndex[letter].idx; col < signIndex[letter].idx+signIndex[letter].len;
col++)
{
if (col >= str1[row].Length)
{
curRowSb.Append(" ");
}
else
curRowSb.Append(str1[row][col]);
}
string emptys = EmptyString(signIndex[letter].len);
//空 或者与上一行相等
//压缩
if (curRowSb.ToString() == emptys || (compressStr[letter].Count > 0
&& compressStr[letter][compressStr[letter].Count - 1] == curRowSb.ToString()))
{
continue;//next row
}
else
{
compressStr[letter].Add(curRowSb.ToString());
}
//清空
curRowSb = null;
}
}
//第二次压缩
List<string>[] compressStr2 = new List<string>[maxLetter];
for (int idx = 0; idx < maxLetter; idx++)
{
compressStr2[idx] = new List<string>();
}
//横向压缩
for (int letter = 0; letter < maxLetter; letter++)
{
for (int col = 0; col < signIndex[letter].len; col++)
{
StringBuilder comp1ColSb = new StringBuilder();
for (int row=0;row<compressStr[letter].Count; row++)
{
if(col<compressStr[letter][row].Length)
comp1ColSb.Append(compressStr[letter][row][col]);
else
comp1ColSb.Append(" ");
}
//已经加到
StringBuilder comp2ColSb = new StringBuilder();
//压缩
if (compressStr2[letter].Count > 0 )
{
//获取letter的col列
for (int row = 0; row < compressStr2[letter].Count; row++)
{
comp2ColSb.Append(compressStr2[letter][row][compressStr2[letter][row].Length-1]);
}
//相等列
if (comp1ColSb.ToString() == comp2ColSb.ToString())
continue;
else//插入列
{
//count 为行数
for (int row = 0; row < compressStr2[letter].Count; row++)
{
//c2ColSb为当前列
compressStr2[letter][row] += comp1ColSb[row].ToString();
}
}
}
else
{
//建立rows
for (int row = 0; row < comp1ColSb.Length; row++)
{
//c2ColSb为当前列
compressStr2[letter].Add(comp1ColSb[row].ToString());
}
}
}
}
//运算
return compute(compressStr2);
}
}
//计算算式
int compute(List<string>[] cps)
{
StringBuilder cti = new StringBuilder();
for (int i = 0; i < cps.Length; i++)
{
StringBuilder sb = new StringBuilder();
for (int j = 0; j < cps[i].Count; j++)
{
sb.Append(cps[i][j]);
}
cti.Append(changetoint(sb.ToString()));
}
//下标
int index=0;
//结果
int tSum=0,resultSum=0;
//存取数
int tp=0;
while(index<cti.Length)
{
tSum = 0;
while(index<cti.Length&& int.TryParse(cti[index++].ToString(),out tp))
{
tSum = tSum * 10 + tp;
}
resultSum+=tSum;
}
return resultSum;
}
//将图像变成数字
char changetoint(string s)
{
switch (s)
{
case "@": return '1';
case "@@@ @@@@@ @@@": return '2';
case "@@ @@@ @@@": return '3';
case "@ @@@@ @": return '4';
case "@@@@ @@@ @@@@": return '5';
case "@@@@ @@@@ @@@@":return '6';
case "@@ @": return '7';
case "@@@@ @@@@@ @@@@": return '8';
case "@@@@ @@@@ @@@@": return '9';
case "@@@@ @@@@": return '0';
default: return '+';
}
}
string EmptyString(int n)
{
StringBuilder sb = new StringBuilder();
while (n-- > 0)
{
sb.Append(" ");
}
return sb.ToString();
}
void print(string[] str, int idx)
{
for(int i=0;i<idx;i++)
{
Console.WriteLine(str[i]);
}
}
static void Main(string[] args)
{
Program p = new Program();
Console.Write(p.adjust().ToString());
Console.ReadLine();
}
}
}
相关文章推荐
- bmp 格式图像印刷体数字的识别
- 数字图像处理:基于MATLAB的车牌识别项目
- 简单的纯数字图像(如电话号码、数字验证码)识别
- 使用ImageMagick和Tesseract进行简单数字图像识别
- 基于机器学习多种方法的kaggle竞赛入门之手写数字的图像识别预测
- 系统学习数字图像处理之目标识别
- 图像识别(13)——手势识别(1)——用matchShapes识别手形数字
- 数字图像处理与识别需要掌握的知识要点
- 通过摄像头捕获图像用tensorflow做手写数字识别
- 数字图像识别——一种场景的实现
- caffe应用-01灰度图像分类之手写体数字识别
- 数字识别--图像预处理(整个过程)
- 手写数字识别(二)----SVM 实现Mnist-image 手写数字图像识别
- 图像基础21 手写数字识别
- 数字图像识别
- 简单的纯数字图像(如电话号码、数字验证码)识别
- bmp 格式图像印刷体数字的识别
- tensorflow构建手写数字图像识别---softmax算法
- 数字图像处理与识别技术概况
- KMeans算法-手写数字图像识别