我看到Neo4j API非常巧妙地使用了ASCII Art:
http://jaxenter.com/getting-started-with-neo4j-the-java-graph-database-47955.html
我想尝试类似的东西,但使用ASCI Art to HTML。如何解析ASCII艺术,例如,给定ASCII艺术输入,如:
--------------------------------
I I
I ------- ------- I
I I I I I I
I I A I I B I I
I I I I I I
I ------- ------- I
I I
I I
--------------------------------
:可能导致HTML输出类似于:
<div>
<div style='display:inline;'>
A
</div>
<div style='display:inline;'>
B
</div>
</div>
问题是封闭的,因为我需要“证明对正在解决的问题的最小理解”。我确实理解要解决的问题。问题是我想要解决的是在以下Web框架的源代码中更容易理解模板化HTML:
https://github.com/zubairq/coils
:虽然该解决方案可以应用于任何Web框架。我已经看到有人试图在C ++中创建一个初始版本:
https://github.com/h3nr1x/asciidivs2html/blob/master/asciidivs2html.cpp
:非常令人印象深刻!如果你能在Java或Clojure中使用它,那么如果我们可以重新打开这个问题,我将提名一个赏金,这样你就可以获得更多积分来解决问题:)
我运行了@meewok提供的Java解决方案,结果如下:
$ java AsciiToDIVs.RunConverter
Created a box(ID=0,X=0,Y=0,width=33,height=10)
Created a box(ID=1,X=2,Y=4,width=8,height=5,parent=0)
Created a char(Char=A,X=4,Y=7,parent=1)
Created a box(ID=2,X=2,Y=21,width=8,height=5,parent=0)
Created a char(Char=B,X=4,Y=24,parent=2)
<div><div><div>A</div></div><div><div>B</div></div></div>
答案 0 :(得分:11)
实施的解决方案如下:
然后我将创建一个算法,当它检测到“ - ”字符时,我将acall初始化为一种方法,以检测字符后面的剩余角落(右上角,左下角,右下角)以及它们结束的位置。
示例(快速伪代码):
while(selectedCell==I)
selectedCell=selectedCell.goDown();
使用这样的策略,您可以绘制出您的方框,以及包含哪些方框。
剩下的就是将此信息打印为html ..
由于我心情愉快,我花了一个小时+来快速烹饪玩具。 以下是非优化的,因为我没有利用迭代器来遍历Cell,并且需要重构才能成为一个严肃的框架。
<强> Cell.java 强>
package AsciiToDIVs;
public class Cell {
public char Character;
public CellGrid parentGrid;
private int rowIndex;
private int colIndex;
public Cell(char Character, CellGrid parent, int rowIndex, int colIndex)
{
this.Character = Character;
this.parentGrid = parent;
this.rowIndex = rowIndex;
this.colIndex = colIndex;
}
public int getRowIndex() {
return rowIndex;
}
public int getColIndex() {
return colIndex;
}
}
<强> CellGrid.java 强>
package AsciiToDIVs;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
public class CellGrid {
private ArrayList<ArrayList<Cell>> CellGridData;
public CellGrid(String asciiFile) throws IOException {
readDataFile(asciiFile);
}
public ArrayList<FoundObject> findBoxes(FoundBoxObject parent)
{
int startRowIndex = 0, startColIndex = 0,
parentRowLimit = Integer.MAX_VALUE,
parentColLimit = Integer.MAX_VALUE,
startingColIndex = 0;
if(parent != null)
{
startRowIndex = parent.getRowIndex()+1;
startColIndex = startingColIndex = parent.getColIndex()+1;
parentRowLimit = parent.getRowIndex() + parent.getHeight();
parentColLimit = parent.getColIndex() + parent.getWidth();
}
ArrayList<FoundObject> results = new ArrayList<FoundObject>();
Cell currentCell;
if(startRowIndex>=CellGridData.size())
return null;
for(; startRowIndex<CellGridData.size() && startRowIndex<parentRowLimit; startRowIndex++ )
{
startColIndex = startingColIndex;
for(; startColIndex< CellGridData.get(startRowIndex).size() && startColIndex<parentColLimit; startColIndex++)
{
FoundBoxObject withinBox = checkWithinFoundBoxObject(results, startRowIndex, startColIndex);
if(withinBox !=null)
startColIndex+=withinBox.getWidth();
currentCell = getCell(startRowIndex, startColIndex);
if(currentCell!=null)
{
if(currentCell.Character == '-') // Found a TOP-CORNER
{
int boxHeight = getConsecutiveIs(startRowIndex+1, startColIndex) + 1;
if(boxHeight>1)
{
int boxWidth = getConsecutiveDashes(startRowIndex, startColIndex);
FoundBoxObject box = new FoundBoxObject(startRowIndex, startColIndex, boxWidth, boxHeight, parent);
results.add(box);
findBoxes(box);
startColIndex+=boxWidth;
}
}
//This is a character
else if(currentCell.Character != '-' && currentCell.Character != 'I' && currentCell.Character != ' '
&& currentCell.Character != '\n' && currentCell.Character != '\n' && currentCell.Character != '\t')
{
FoundCharObject Char = new FoundCharObject(startRowIndex, startColIndex, parent, currentCell.Character);
results.add(Char);
}
}
}
}
if(parent!=null)
parent.containedObjects = results;
return results;
}
public static String printDIV(ArrayList<FoundObject> objects)
{
String result = "";
Iterator<FoundObject> it = objects.iterator();
FoundObject fo;
while(it.hasNext())
{
result+="<div>";
fo = it.next();
if(fo instanceof FoundCharObject)
{
FoundCharObject fc = (FoundCharObject)fo;
result+=fc.getChar();
}
if(fo instanceof FoundBoxObject)
{
FoundBoxObject fb = (FoundBoxObject)fo;
result+=printDIV(fb.containedObjects);
}
result+="</div>";
}
return result;
}
private FoundBoxObject checkWithinFoundBoxObject(ArrayList<FoundObject> results, int rowIndex, int colIndex)
{
Iterator<FoundObject> it = results.iterator();
FoundObject f;
FoundBoxObject fbox = null;
while(it.hasNext())
{
f = it.next();
if(f instanceof FoundBoxObject)
{
fbox = (FoundBoxObject) f;
if(rowIndex >= fbox.getRowIndex() && rowIndex <= fbox.getRowIndex() + fbox.getHeight())
{
if(colIndex >= fbox.getColIndex() && colIndex <= fbox.getColIndex() + fbox.getWidth())
{
return fbox;
}
}
}
}
return null;
}
private int getConsecutiveDashes(int startRowIndex, int startColIndex)
{
int counter = 0;
Cell cell = getCell(startRowIndex, startColIndex);
while( cell!=null && cell.Character =='-')
{
counter++;
cell = getCell(startRowIndex, startColIndex++);
}
return counter;
}
private int getConsecutiveIs(int startRowIndex, int startColIndex)
{
int counter = 0;
Cell cell = getCell(startRowIndex, startColIndex);
while( cell!=null && cell.Character =='I')
{
counter++;
cell = getCell(startRowIndex++, startColIndex);
}
return counter;
}
public Cell getCell(int rowIndex, int columnIndex)
{
ArrayList<Cell> row;
if(rowIndex<CellGridData.size())
row = CellGridData.get(rowIndex);
else return null;
Cell cell = null;
if(row!=null){
if(columnIndex<row.size())
cell = row.get(columnIndex);
}
return cell;
}
public Iterator<ArrayList<Cell>> getRowGridIterator(int StartRow) {
Iterator<ArrayList<Cell>> itRow = CellGridData.iterator();
int CurrentRow = 0;
while (itRow.hasNext()) {
// Itrate to Row
if (CurrentRow++ < StartRow)
itRow.next();
}
return itRow;
}
private void readDataFile(String asciiFile) throws IOException {
CellGridData = new ArrayList<ArrayList<Cell>>();
ArrayList<Cell> row;
FileInputStream fstream = new FileInputStream(asciiFile);
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
// Read File Line By Line
int rowIndex = 0;
while ((strLine = br.readLine()) != null) {
CellGridData.add(row = new ArrayList<Cell>());
// System.out.println (strLine);
for (int colIndex = 0; colIndex < strLine.length(); colIndex++) {
row.add(new Cell(strLine.charAt(colIndex), this, rowIndex,colIndex));
// System.out.print(strLine.charAt(i));
}
rowIndex++;
// System.out.println();
}
// Close the input stream
br.close();
}
public String printGrid() {
String result = "";
Iterator<ArrayList<Cell>> itRow = CellGridData.iterator();
Iterator<Cell> itCol;
Cell cell;
while (itRow.hasNext()) {
itCol = itRow.next().iterator();
while (itCol.hasNext()) {
cell = itCol.next();
result += cell.Character;
}
result += "\n";
}
return result;
}
}
<强> FoundBoxObject.java 强>
package AsciiToDIVs;
import java.util.ArrayList;
public class FoundBoxObject extends FoundObject {
public ArrayList<FoundObject> containedObjects = new ArrayList<FoundObject>();
public static int boxCounter = 0;
public final int ID = boxCounter++;
public FoundBoxObject(int rowIndex, int colIndex, int width, int height, FoundBoxObject parent) {
super(rowIndex, colIndex, width, height);
if(parent!=null)
System.out.println("Created a box(" +
"ID="+ID+
",X="+rowIndex+
",Y="+colIndex+
",width="+width+
",height="+height+
",parent="+parent.ID+")");
else
System.out.println("Created a box(" +
"ID="+ID+
",X="+rowIndex+
",Y="+colIndex+
",width="+width+
",height="+height+
")");
}
}
<强> FoundCharObject.java 强>
package AsciiToDIVs;
public class FoundCharObject extends FoundObject {
private Character Char;
public FoundCharObject(int rowIndex, int colIndex,FoundBoxObject parent, char Char) {
super(rowIndex, colIndex, 1, 1);
if(parent!=null)
System.out.println("Created a char(" +
"Char="+Char+
",X="+rowIndex+
",Y="+colIndex+
",parent="+parent.ID+")");
else
System.out.println("Created a char(" +
",X="+rowIndex+
",Y="+colIndex+")");
this.Char = Char;
}
public Character getChar() {
return Char;
}
}
<强> FoundObject.java 强>
package AsciiToDIVs;
public class FoundObject {
private int rowIndex;
private int colIndex;
private int width = 0;
private int height = 0;
public FoundObject(int rowIndex, int colIndex, int width, int height )
{
this.rowIndex = rowIndex;
this.colIndex = colIndex;
this.width = width;
this.height = height;
}
public int getRowIndex() {
return rowIndex;
}
public int getColIndex() {
return colIndex;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
主要方法
public static void main(String args[])
{
try {
CellGrid grid = new CellGrid("ascii.txt");
System.out.println(CellGrid.printDIV(grid.findBoxes(null)));
//System.out.println(grid.printGrid());
} catch (IOException e) {
e.printStackTrace();
}
}
'printDIV'应该是这样的(打印的数量超过了需要的数量)。
public static String printDIV(ArrayList<FoundObject> objects)
{
String result = "";
Iterator<FoundObject> it = objects.iterator();
FoundObject fo;
while(it.hasNext())
{
fo = it.next();
if(fo instanceof FoundCharObject)
{
FoundCharObject fc = (FoundCharObject)fo;
result+=fc.getChar();
}
if(fo instanceof FoundBoxObject)
{
result+="<div>";
FoundBoxObject fb = (FoundBoxObject)fo;
result+=printDIV(fb.containedObjects);
result+="</div>";
}
}
return result;
}
答案 1 :(得分:5)
这是一个相当简单的JavaScript解决方案,通过Node进行测试。当然,您需要调整输入和输出方法。
var s = "\n\
--------------------------------\n\
I I\n\
I ------- ------- I\n\
I I I I I I\n\
I I A I I B I I\n\
I I I I I I\n\
I ------- ------- I\n\
I I\n\
I I\n\
--------------------------------\n\
";
var lines = s.split('\n');
var outer_box_top_re = /--+/g;
var i;
for (i=0; i<lines.length; i++) {
while ((res = outer_box_top_re.exec(lines[i])) != null) {
L = res.index
R = outer_box_top_re.lastIndex
process_box(i, L, R)
}
}
function process_box(T, L, R) {
console.log('<div top="' + T + '" left="' + L + '" right="' + R + '">')
blank_out(T, L, R)
var i = T;
while (1) {
i += 1;
if (i >= lines.length) {
console.log('Fell off bottom of ascii-art without finding bottom of box');
process.exit(1);
}
var line = lines[i];
if (line[L] == 'I' && line[R-1] == 'I') {
// interior
// Look for (the tops of) sub-boxes.
// (between L+1 and R-2)
var inner_box_top_re = /--+/g;
// Inner and outer need to be separate so that
// inner doesn't stomp on outer's lastIndex.
inner_box_top_re.lastIndex = L+1;
while ((res = inner_box_top_re.exec(lines[i])) != null) {
sub_L = res.index;
sub_R = inner_box_top_re.lastIndex;
if (sub_L > R-1) { break; }
process_box(i, sub_L, sub_R);
}
// Look for any other content (i.e., a box label)
content = lines[i].substring(L+1, R-1);
if (content.search(/[^ ]/) != -1) {
console.log(content);
}
blank_out(i, L, R);
}
else if (line.substring(L,R).match(/^-+$/)) {
// bottom
blank_out(i, L, R);
break;
}
else {
console.log("line " + i + " doesn't contain a valid continuation of the box");
process.exit(1)
}
}
console.log('</div>')
}
function blank_out(i, L, R) {
lines[i] = (
lines[i].substring(0,L)
+ lines[i].substring(L,R).replace(/./g, ' ')
+ lines[i].substring(R)
);
}
答案 2 :(得分:1)
你想要的是二维解析的想法,它可以检测2D实体并验证它们是否具有合法的关系。
请参阅http://mmi.tudelft.nl/pub/siska/TSD%202DVisLangGrammar.pdf
定义可能的“ASCII艺术”约束集合将是困难的。 只想识别字母吗?仅由相同字母的字符组成? “草书”字母?盒子? (你的例子有方框,其边不是相同的 ASCII字符)。任意厚墙的盒子?嵌套盒子?带(薄/脂)箭头的图表?基尔罗伊 - 是 - 在这里 - 鼻子 - 过度的墙? 蒙娜丽莎的图片,其中字符像素提供密度关系? “ASCII艺术”究竟是什么意思?
真正的问题是定义您想要识别的事物的范围。如果 你限制这个范围,你的成功几率上升(参见参考文献)。
这里的问题与Java或Javascript没有什么关系。这更为相关 算法。选择有限的艺术类,选择正确的算法,然后你所拥有的是一个编码问题,应该相对容易解决。没有限制,没有算法 - &gt;没有任何Javascript可以帮助您。
答案 3 :(得分:0)
假设您已经生成了ASCII艺术品。
在HTML中,您需要做两件事。
<space> to line break to <br/> etc