Java: 1523 1512 caractères
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;}}
Il donne cette sortie pour l'entrée échantillon:
(~(((5)X(4))O(3)))a(~(1))
((~(((5)X(4))O(3)))a(~(1)))X(((2)x(1))x(3))
Afin de serrer sa taille:
- Il n'effectue aucune vérification d'erreur, traitement d'erreur ou validation d'entrée, en supposant que l'entrée est toujours valide.
- Est limité à 99 lignes d'entrée.
- Son fichier d'entrée doit être appelé juste
r
, sans aucune extension de fichier dans le nom.
- Il ne fait aucun effort pour détecter si les parenthèses sont ou ne sont pas nécessaires. Cela suppose qu'ils sont toujours nécessaires, et puisque cette hypothèse est fausse, il y a beaucoup plus de parenthèses que nécessaire, mais comme cela ne fait pas échouer la spécification de toute façon, ce n'est pas un problème.
- L'ordre des paramètres pour chaque opérateur binaire est en général imprévisible, car il dépend de la vitesse de propagation des valeurs et de l'ordre de balayage des cellules. Mais comme tous les opérateurs binaires sont commutatifs, cela ne devrait poser aucun problème.
Je suis sûr qu'il devrait être possible de le réduire davantage, mais juste un peu.
L'interpréteur est implémenté sous la forme d'une sorte d'automate cellulaire. Il scanne l'intégralité des valeurs de réglage sur place, en les répétant autant de fois que nécessaire jusqu'à ce qu'aucun changement ne soit détecté.
Voici une version non golfée:
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;
}
}