Java: 1523 1512 chars
import java.util.*;class W{int v=99;Map<Integer,String>t;boolean k;public static void main(String[]y){new W().d();}W(){try{java.io.InputStream i=new java.io.File("r").toURL().openStream();t=new HashMap<>();int a=0,x=0,y=0;while((a=i.read())>-1){if(a==10){y++;x=0;continue;}q(x,y,(a>47&a<58?"!":"")+(char)a);x++;}}catch(Exception e){}}void d(){while(!k){k=!k;for(Map.Entry<Integer,String>g:t.entrySet())e(g.getKey(),g.getValue());}for(String b:t.values())if(b.startsWith("$"))System.out.println(b.substring(1));}void e(int a,String s){if(s==null||!s.startsWith("!"))return;int x=a/v,y=a%v;s=s.substring(1);b(s,x,y,x-1,y+1);b(s,x,y,x,y+1);b(s,x,y,x+1,y+1);b(s,x,y,x-1,y);b(s,x,y,x+1,y);b(s,x,y,x-1,y-1);b(s,x,y,x,y-1);b(s,x,y,x+1,y-1);}void b(String p,int m,int n,int x,int y){String s=t.get(x*v+y);if(s==null)return;boolean g=y==n+1;boolean h=y==n-1;boolean i=x==m+1;boolean j=x==m-1;if(z(s,"-=")&n==y){if(i)b(p,x,y,x+1,y);if(j)b(p,x,y,x-1,y);}if(z(s,"|=")&m==x){if(g)b(p,x,y,x,y+1);if(h)b(p,x,y,x,y-1);}if(z(s,"/=")){if(j&g)b(p,x,y,x-1,y+1);if(i&h)b(p,x,y,x+1,y-1);}if(z(s,"\\=")){if(i&g)b(p,x,y,x+1,y+1);if(j&h)b(p,x,y,x-1,y-1);}if(z(s,".")){q(x,y,"!"+p);u();}if(z(s,"~")){q(x,y,"!~("+p+")");u();}if((s.charAt(0)=='%'&n==y-1)|(s.charAt(0)=='&'&n==y+1)){q(x,y,"!("+p+")"+s.charAt(1)+"("+s.substring(2)+")");u();}if(z(s,"OoAaXx")){q(x,y,(n==y+1?"%":"&")+s+p);u();}if(z(s,":")){q(x,y,"$"+p);u();}}void q(int x,int y,String z){t.put(x*v+y,z);}void u(){k=false;}boolean z(String s,String c){return c.indexOf(s)>-1;}}
It gives this output for the sample input:
(~(((5)X(4))O(3)))a(~(1))
((~(((5)X(4))O(3)))a(~(1)))X(((2)x(1))x(3))
In order to squeeze its size:
- It does not do any error checking, error handling or input validation, assuming that the input is always valid.
- Is limited to 99 lines of input.
- Its input file must be called just
r
, without any file extension in the name.
- It does not makes any effort to detect if the parenthesis are or aren't necessary. It assumes that they always are necessary, and since this assumption is false, there is a lot more parenthesis than needed, but since this does not makes it fail the spec anyway, it is no problem.
- The order of the parameters to each binary operator is in general unpredictable, as it depends on the velocity that the values are propagated and from cell scanning order. But since all the binary operators are commutative, this should be no problem.
I am sure that it should be possible to reduce it more, but just a bit.
The interpreter is implemented in the form of some sort of cellular automata. It scans the entire field setting values, repeating it as many times as needed until no changes are detected.
Here is an ungolfed version:
import java.util.*;
class Wiring {
int maxLines = 99;
Map<Integer, String> circuitState;
boolean finished;
public static void main(String[] args) {
new Wiring().interpret();
}
Wiring() {
try {
// Always read the input from the "r" file, and do not check if it even
// exists. BTW, the toURL() method is deprecated, but we don't care about
// this in code-golfing.
java.io.InputStream stream = new java.io.File("r").toURL().openStream();
circuitState = new HashMap<>();
int byteRead = 0, cellX = 0, cellY = 0;
while ((byteRead = stream.read()) > -1) {
// Check for line break;
if (byteRead == 10) {
cellY++;
cellX = 0;
continue;
}
// Populate the circuit cell. Precede numbers with an exclamation mark.
setCircuitCell(cellX, cellY, (byteRead >= '0' & byteRead <= '9' ? "!" : "") + (char) byteRead);
cellX++;
} catch (Exception e) {
}
}
void interpret() {
while (!finished) {
finished = !finished; // i.e. finished = false;
for (Map.Entry<Integer, String> entry : circuitState.entrySet()) {
analyzeCell(entry.getKey(), entry.getValue());
}
}
// Now print the output. To do that scan for cells marked with "$".
for (String cell : circuitState.values()) {
if (cell.startsWith("$")) System.out.println(cell.substring(1));
}
}
void analyzeCell(int cellIndex, String cellValue) {
// Only the cells with a value marked with "!" are worth to analyze.
if (cellValue == null || !cellValue.startsWith("!")) return;
// Convert the cellIndex to a bidimensional coordinate.
int x = cellIndex / maxLines, y = cellIndex % maxLines;
// Remove the "!".
cellValue = cellValue.substring(1);
// Propagate the cell value to neighbouring cells.
propagateCellData(cellValue, x, y, x - 1, y + 1);
propagateCellData(cellValue, x, y, x, y + 1);
propagateCellData(cellValue, x, y, x + 1, y + 1);
propagateCellData(cellValue, x, y, x - 1, y);
propagateCellData(cellValue, x, y, x + 1, y);
propagateCellData(cellValue, x, y, x - 1, y - 1);
propagateCellData(cellValue, x, y, x, y - 1);
propagateCellData(cellValue, x, y, x + 1, y - 1);
}
void propagateCellData(String cellValue, int sourceX, int sourceY, int targetX, int targetY) {
String targetContent = circuitState.get(targetX * maxLines + targetY);
// If the target cell does not exist, just ignore.
if (targetContent == null) return;
boolean targetBelowSource = targetY == sourceY + 1;
boolean targetAboveSource = targetY == sourceY - 1;
boolean targetRightToSource = targetX == sourceX + 1;
boolean targetLeftToSource = targetX == sourceX - 1;
// Propagate horizontally through wires.
if (isStringContained(targetContent, "-=") & sourceY == targetY) {
if (targetRightToSource) propagateCellData(cellValue, targetX, targetY, targetX + 1, targetY);
if (targetLeftToSource) propagateCellData(cellValue, targetX, targetY, targetX - 1, targetY);
}
// Propagate vertically.
if (isStringContained(targetContent, "|=") & sourceX == targetX) {
if (targetBelowSource) propagateCellData(cellValue, targetX, targetY, targetX, targetY + 1);
if (targetAboveSource) propagateCellData(cellValue, targetX, targetY, targetX, targetY - 1);
}
// Propagate in the diagonal x=-y.
if (isStringContained(targetContent, "/=")) {
if (targetLeftToSource & targetBelowSource) {
propagateCellData(cellValue, targetX, targetY, targetX - 1, targetY + 1);
}
if (targetRightToSource & targetAboveSource) {
propagateCellData(cellValue, targetX, targetY, targetX + 1, targetY - 1);
}
}
// Propagate in the diagonal x=y.
if (isStringContained(targetContent, "\\=")) {
if (targetRightToSource & targetBelowSource) {
propagateCellData(cellValue, targetX, targetY, targetX + 1, targetY + 1);
}
if (targetLeftToSource & targetAboveSource) {
propagateCellData(cellValue, targetX, targetY, targetX - 1, targetY - 1);
}
}
// If we got a dot, store the value there.
// Do not forget to mark it with "!", so we can rescan it later.
if (isStringContained(targetContent, ".")) {
setCircuitCell(targetX, targetY, "!" + cellValue);
markThatStateChanged();
}
// If we got a "~", store the inverted value there.
// Do not forget to mark it with "!", so we can rescan it later.
if (isStringContained(targetContent, "~")) {
setCircuitCell(targetX, targetY, "!~(" + cellValue + ")");
markThatStateChanged();
}
// If we found a binary logical port with one of the values set and
// we can set the another value, do it. Use "%" and "&" to know which
// one was already defined.
// BTW, do not forget to mark it with "!", so we can rescan it later.
if ((targetContent.charAt(0) == '%' & sourceY == targetY - 1)
| (targetContent.charAt(0) == '&' & sourceY == targetY + 1))
{
setCircuitCell(targetX, targetY,
"!(" + cellValue + ")"
+ targetContent.charAt(1)
+ "(" + targetContent.substring(2) + ")");
markThatStateChanged();
}
// Found a binary logical port without any value setted, so set it.
// Use "%" and "&" to mark which one was setted.
if (isStringContained(targetContent, "OoAaXx")) {
setCircuitCell(targetX, targetY, (sourceY == targetY + 1 ? "%" : "&") + targetContent + cellValue);
markThatStateChanged();
}
// If we found an output, store the value there.
// Mark it with "$", so we will print it in the future.
if (isStringContained(targetContent, ":")) {
setCircuitCell(targetX, targetY, "$" + cellValue);
markThatStateChanged();
}
}
void setCircuitCell(int cellX, int cellY, String cellContents) {
circuitState.put(cellX * maxLines + cellY, cellContents);
}
void markThatStateChanged() {
finished = false;
}
boolean isStringContained(String searchingString, String searchTarget) {
return searchTarget.indexOf(searchingString) > -1;
}
}