Java: 1523 1512 caracteres
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;}}
Ele fornece esta saída para a entrada de amostra:
(~(((5)X(4))O(3)))a(~(1))
((~(((5)X(4))O(3)))a(~(1)))X(((2)x(1))x(3))
Para diminuir seu tamanho:
- Ele não realiza nenhuma verificação de erro, tratamento de erros ou validação de entrada, assumindo que a entrada seja sempre válida.
- É limitado a 99 linhas de entrada.
- Seu arquivo de entrada deve ser chamado apenas
r
, sem nenhuma extensão de arquivo no nome.
- Não faz nenhum esforço para detectar se os parênteses são ou não necessários. Ele pressupõe que eles sempre são necessários e, como essa suposição é falsa, há muito mais parênteses do que o necessário, mas como isso não faz com que as especificações falhem, não há problema.
- A ordem dos parâmetros para cada operador binário é geralmente imprevisível, pois depende da velocidade em que os valores são propagados e da ordem de varredura da célula. Mas como todos os operadores binários são comutativos, isso não deve ser problema.
Estou certo de que deve ser possível reduzi-lo mais, mas apenas um pouco.
O intérprete é implementado na forma de algum tipo de autômato celular. Ele verifica todos os valores de configuração do campo, repetindo-o quantas vezes forem necessárias até que nenhuma alteração seja detectada.
Aqui está uma versão não destruída:
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;
}
}