회로도 해석


12

논리 게이트로 완성 된 회로도를 해석해야합니다.

논리 게이트 (실제로이 과제를 완료하기 위해 이들이 무엇을해야하는지 알 필요는 없음) :

  • 그리고 게이트 : a
  • 또는 게이트 : o
  • 낸드 게이트 : A
  • 도 게이트 : O
  • xor 게이트 : x
  • xnor 게이트 : X
  • 게이트 아님 : ~

각 게이트이지만 마지막 게이트는 두 개의 입력을받습니다. 입력은 .게이트를 중심으로 한 3 x 3 정사각형의 왼쪽 상단 및 왼쪽 하단에 있습니다. 그렇지 않은 경우 입력은 직접 왼쪽에 있습니다. 출력은 .오른쪽 으로 직접 전달됩니다.

전선은 -|\/.=

  • - 두 개의 전선, 하나는 오른쪽, 하나는 왼쪽에 접촉합니다. c-c
  • | 하나의 위와 아래의 두 개의 와이어에 접촉합니다.

    c
    |
    c
    
  • /\작업은 다음과 같습니다 :

    c        c
     \      /
      c    c
    
  • . 모든 주변 와이어에 접촉 :

    ccc
    c.c
    ccc
    
  • =특별하다. 인접한 전선을 연결합니다.

    -=-
    

    두 전선을 연결합니다. 다음에서

    \|/
    -=-
    /|\
    

    반대쪽 와이어는 서로 연결되어 있지만 다른 와이어는 서로 연결되어 있지 않습니다 (여기서는 다른 위치 .).

  • 전류가 흐르려면 두 개의 전선이 다른 하나에 연결되어 있어야하므로 |-전류가 흐르지 않습니다 .

배선 예 :

      .-.
     =   \
 .--. .---=---
-.   =     .--
 .--. .-------

입력은 두 개의 와이어로 분할 된 다음 세 개의 와이어로 분할됩니다. 이 분할에서 하단 와이어는 중간으로 이동하고 상단 와이어의 아래쪽 분할은 하단에 나타납니다. 다음으로 세 와이어의 상단이 중간으로 이동합니다.

게이트가있는 샘플 배선 :

--.
   o..~..
--.      o.---
   a.---.
--.

입력 형식 :

  • 각 입력 와이어에는 숫자가 표시됩니다. 말 (오른쪽 줄 바꿈 전)에서, 각각의 출력으로 표시됩니다 :(와이어는 항상 갈 권리 , 즉 그것으로 -:또는 .:=:)
  • 입력은 항상 유효합니다. 게이트없이 연결되는 루프 나 와이어는 없습니다. 끝이 느슨한 전선이있을 수 있습니다.
  • = 필요한 경우에만 사용됩니다.

출력 형식:

  • 각 입력은 해당 번호로 참조됩니다.
  • 식이 출력됩니다. 예를 들어, 와이어가 입력 1과 입력 2를 계산하면 출력은 1a2입니다.
  • 출력되는 모든 기능은 시작시 로직 게이트에 해당해야합니다.
  • 표시하지 않으려면 ~앞에 올바른 장소를 두십시오.
  • 여러 함수의 경우 괄호를 사용하여 실행 순서를 표시하십시오. 함수가 하나 뿐인 경우에도 괄호를 사용할 수 있습니다. 예를 들어

    1-.~.-.
           A.~.-:
          .
    2-.  /
       x.
    3-.
    

    하나의 가능한 출력이 ~((2x3)A(~1))

  • 여러 출력은 개행 (또는 동등한)으로 분리되어야합니다.

샘플 입력 :

1--.---.
    x.  \
2--.  x.-=---------.
     .    .~.       X.--.
3---. .      a.----.   /
       O.~.-.       \ /
      .              =
4-.  /              / .-:
   X.              .----:
5-.

하나의 가능한 해당 출력 :

(~1)a(~(3O(4X5))
((1x2)x3)X((~1)a(~(3O(4X5))))

Oooohhhh, 재미있는! 나는 그것을 줄 것이다.
cjfaure

5
Turing-complete를 만드는 방법으로 확장하면 흥미로운 exolang이 나올 것입니다.
Victor Stafusa

"컴파일러 오류"(예 : 잘못된 입력 배선)의 경우 인터프리터는 어떻게해야합니까?
Victor Stafusa

그리고 두 개의 입력을 직접 연결하면? 아니면 두 개의 출력을 직접 연결 하시겠습니까? 아니면 출력에 개방 라인을 입력합니까?
Victor Stafusa

1
@Victor 이것은 이미 비슷합니다. 그러나 나는 다른 하나를
Justin

답변:


4

파이썬 2,488 1,567 806 706 697 657 653

예를 들어 gzip + exec!

import zlib,base64;exec zlib.decompress(base64.b64decode('eNp1U8FuqzAQvPMV7sm2gBSuuFupX9BLD5UoBxNMMAkEgQmJVPXb364Daiu9ntaznt2dWYzthvPo2HSbgsrU7E3so0FmAWtgnyeFshjSImC2Zs1Tws4js/fQPMPJ9KKTlFrPeVPIbDRuHnvOA3YByuS2UCNwrloYqOMRQ1ooDY0qwaoKRJxGSZRKP+QCwBn/0YRyzPYcYq77irUATVbGcIytGkN4E7mOyiLayx/MT888AthMx9DGDTLj/zIfPz44emUGqC/Zoio1UdFzohzFp0TNNA7xQhFxDWJiNGNG98L54yLVYUsv3+kZx9G8/uyEoQFk8NELrDeIIggf5Cb3b3/I3nnFNdZe0QOrCHl4+4ZsgVyH16gMb4XHq4IrwA0gkV7kAwyZH7Fs7f0S/O7IbnZX7jelzy+v13f8LsAFD0kVfrQyTklZyCUPL+F2Ef66WHug7i9f/bWyfnOIsrNTZQ/WCXxCcAnY/QmwMeggLwIyeCKD+FB3k6tsj/K6nR4G01fiZCcnTlIGBkw/d2bUzvgSG2kqMvhOkU+ZNirvGS1XgyWKy/xS2TDa3uE/kNuoJX0UC/kP8j/kmA=='))

한계와 가정

그대로 최대 9 개의 입력 만 지원되며 여러 자리가 올바르게 처리되지 않습니다. 사양은 입력이 함께 표시된 것을 나타내는 바와 같이 숫자 가 아닌 숫자 이 허용된다.


입력과 출력

입력은 표준 입력을 통해 이루어지고 출력은 표준 출력을 통해 이루어집니다.


테스팅

샘플 입력 및 출력 :

1--.---.
    x.  \
2--.  x.-=---------.
     .    .~.       X.--.
3---. .      a.----.   /
       O.~.-.       \ /
      .              =
4-.  /              / .-:
   X.              .----:
5-.


(~(1))a(~((3)O((4)X(5))))
(((1)x(2))x(3))X((~(1))a(~((3)O((4)X(5)))))

여기에서 테스트되었습니다 : http://ideone.com/gP4CIq


알고리즘

기본적으로 출력에서 ​​다소 순진한 DFS입니다. 각 출력에 대해 문자 1에서 왼쪽으로 시작하여 모든 게이트에서 분기 (및 표현식에 추가)하여 와이어를 추적합니다. 입력에 도달하면 게이트에 분기가 불가능 하다는 것을 확신 할 수 있기 때문에 입력에 도달하고 분기 된 마지막 지점까지 역 추적합니다 . 물론 유효하지 않은 경우는 버려집니다. 그다지 특별한 점은 없으므로 이전보다 오래되었을 것입니다.


노트

약간의 구조 조정으로 크기가 상당히 줄어들 수 있지만 오늘은 이것에 충분한 시간을 보냈습니다. 수동으로 골프 버전은 압축 된 버전이었습니다.

gzip 압축은 특정 캐싱 (예 d=(-1,0,1):)이 실제로 압축 알고리즘이 처리하는 것보다 더 많은 공간을 차지 하기 때문에 골프를 흥미롭게 만듭니다 . 그러나 압축을 최적화하지 않고 가능한 한 수동 버전을 선택했습니다.


수동 (golfed 909 895 840 803) :

import sys
def T(c,p):
 h=c[0];i=c[1]
 if h<0 or i<0 or h>=len(m)or i>=len(m[h]):return''
 v=m[h][i];r='';j=p[0];k=p[1];a=h;b=i;d=(-1,0,1)
 if v==' ':return''
 if v in'=-'and j==h:b-=k-i;r+=T([a,b],c)
 if v in'=|'and k==i:a-=j-h;r+-T([a,b],c)
 if v in'=/\\':
  e=j==h or k==i;s=j-h>0;t=j-h<0;u=k-i>0;w=k-i<0;f=(s and u)or(t and w);g=(s and w)or(t and u)
  if not(e or v=='/'and f or v=='\\'and g):a-=j-h;b-=k-i;r+=T([a,b],c)
 if v=='.':
  for x in d:
   for y in d:
    w=[a+x,b+y]
    if not(x==y==0)and w!=p:r+=T(w,c)
 if j==h and k-i>0:
  if v in'aoAOxX':r='('+T([a-1,b-1],c)+')'+v+'('+T([a+1,b-1],c)+')'
  if v=='~':r='~('+T([a,b-1],c)+')'
 if v.isdigit():r=v
 return r
m=[]
for l in sys.stdin:
 m.append(list(l))
e=enumerate
for i,a in e(m):
 for j,b in e(a):
  if b==':':
   print T([i,j-1],[i,j])

풀 골프 (2488) :

import sys

def findOuts(c):
    for i, iVal in enumerate(c):
        for j, jVal in enumerate(iVal):
            if jVal == ':':
                yield [i, j]

def trace(pos, prev):
    if pos[0] < 0 or pos[1] < 0 or pos[0] >= len(circuit) or pos[1] >= len(circuit[pos[0]]):
        return ''
    val = circuit[pos[0]][pos[1]]
    if val == ' ':
        return ''
    next = pos[:]
    ret = ''
    if val in '=-':
        if prev[0] == pos[0]:
            next[1] -= prev[1] - pos[1]
            ret += trace(next, pos)
    if val in '=|':
        if prev[1] == pos[1]:
            next[0] -= prev[0] - pos[0]
            ret += trace(next, pos)
    if val in '=/\\':
        # top-bottom, left-right
        tblr = prev[0] == pos[0] or prev[1] == pos[1]
        # top-left, bottom-right
        tlbr = (prev[0] - pos[0] == 1 and prev[1] - pos[1] == 1) or (prev[0] - pos[0] == -1 and prev[1] - pos[1] == -1)
        # top-right, bottom-left
        trbl = (prev[0] - pos[0] == 1 and prev[1] - pos[1] == -1) or (prev[0] - pos[0] == -1 and prev[1] - pos[1] == 1)
        if not ((val == '/' and (tlbr or tblr)) or (val == '\\' and (trbl or tblr)) or (val == '=' and tblr)):
            next[0] -= prev[0] - pos[0]
            next[1] -= prev[1] - pos[1]
            ret += trace(next, pos)

    if val == '.':
        for x in (-1,0,1):
            for y in (-1,0,1):
                if x == y == 0:
                    continue

                w = [next[0] + x, next[1] + y]
                if w == prev:
                    continue

                # only one of them should return anything
                ret += trace(w, pos)

    # assumption that a logic gate always has a . on its connections, as according to spec
    if val in 'aoAOxX':
        # only from the right/output
        if not (prev[0] == pos[0] and prev[1] == pos[1] + 1):
            return ret
        ret = '(' + trace([next[0] - 1, next[1] - 1], pos) + ')' + val + '(' + trace([next[0] + 1, next[1] - 1], pos) + ')'

    if val == '~':
        # only from the right/output
        if not (prev[0] == pos[0] and prev[1] == pos[1] + 1):
            return ret
        ret = '~(' + trace([next[0], next[1] - 1], pos) + ')'

    if val in '123456789':
        ret = val

    return ret

circuit = []
for line in sys.stdin.readlines():
    # padding added to prevent index out of bounds later
    circuit.append(list(line))

for out in findOuts(circuit):
    next = out[:]
    next[1] -= 1
    print trace(next, out)

DFS 란 무엇입니까? 또한 출력에서 ​​뒤로 작업하는 것이 정확히 내가 생각한 것입니다.
Justin

@Quincunx 깊이 우선 검색. 기본적으로 재귀 (또는 다른 방법으로 LIFO 구문 사용, 스택)는 막 다른 길이나 목표에 도달 할 때까지 경로를 따라 가능한 한 멀리 여행합니다.이 시점에서 마지막 발산 지점으로 돌아가 다른 경로를 시도합니다.

입력에 대한 좋은 가정. 그것이 바로 제가 의미 한 바입니다 (그리고 나는 그것을 제안하기 위해 말하려고했습니다). 그러나 프로그램 0이 숫자로 작동 합니까? 어떻게 교체 주문에 대한 그 때문에 2전에 오는 1등,
저스틴

@Quincunx 필자 는 말할 수 .isdigit()있는 한 파이썬 과 효과적으로 동등한 파이썬을 사용 [0-9]하고 있습니다. 사양에 따라 맞습니까? 교체 된 주문이란 무엇입니까? 구현 방식에 따라 로직 게이트의 상향 분기로 향하지만 입력 순서를 보장 할 수는 없습니다.
Bob

isdigit()일관성이 있습니다. 스와핑 된 순서 2는 첫 번째 입력 및 1두 번째 입력 (수직 정렬) 과 같은 것을 의미합니다 .
저스틴

6

자바 : 1523 1512 자

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;}}

샘플 입력에 대해 다음 출력을 제공합니다.

(~(((5)X(4))O(3)))a(~(1))
((~(((5)X(4))O(3)))a(~(1)))X(((2)x(1))x(3))

크기를 짜려면 :

  • 입력이 항상 유효하다고 가정하면 오류 검사, 오류 처리 또는 입력 유효성 검사를 수행하지 않습니다.
  • 99 라인 입력으로 제한됩니다.
  • 입력 파일 r이름은 파일 확장자없이 just로만 호출해야합니다 .
  • 괄호가 필요한지 여부를 감지하기 위해 노력하지 않습니다. 그것들은 항상 필요하다고 가정하고,이 가정이 거짓이기 때문에 필요한 것보다 훨씬 많은 괄호가 있지만, 이것이 사양을 실패시키지 않기 때문에 아무런 문제가 없습니다.
  • 각 이항 연산자에 대한 매개 변수의 순서는 값이 전파되는 속도와 셀 스캐닝 순서에 따라 다르므로 일반적으로 예측할 수 없습니다. 그러나 모든 이진 연산자는 정식이므로 문제가되지 않습니다.

더 줄일 수는 있지만 조금만 가능하다고 확신합니다.

인터프리터는 일종의 셀룰러 오토마타 형태로 구현됩니다. 전체 필드 설정 값을 스캔하여 변경 사항이 감지되지 않을 때까지 필요한만큼 반복합니다.

ungolfed 버전은 다음과 같습니다.

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;
    }
}

try{}catch(Exception e){}두 개보다 사용하는 것이 조금 저렴합니다 throws Exception. 아마도 다른 것들이 있을지 모르지만, Java를 골프화하는 방법을 모른다.
Bob

@ 밥 고마워, 당신의 제안은 그것을 7 자로 줄였습니다. 또한 4 개를 더 줄일 수 있습니다.
Victor Stafusa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.