ASCII 아트 로직 게이트 다이어그램


12

방정식의 곱 형태에 대한 (확장 된) ASCII 예술 논리 게이트 다이어그램을 작성하는 코드를 작성하도록 요청합니다.

게이트를 나타내려면 다음 표기법을 사용하십시오.

    INPUT───|&&
            |&&───OUTPUT
    INPUT───|&&
또는
    INPUT───|OR
            |OR───OUTPUT
    INPUT───|OR  
입력이 2 개 이상인 게이트
    INPUT───|OR
            |OR
    INPUT───|OR───OUTPUT
            |OR
    INPUT───|OR
아니
    INPUT───│>o───OUTPUT

문자 세트

참고 아스키 파이프 기호 있지만없는 상자 그리기 문자 . ─ │ ┌ ┐ └ ┘연결 과 같은 상자 그리기 문자를 사용하십시오 .

입력
    A'*B'+B*C
산출
    A────│>o────│&&
                │&&─────┐
    B────│>o────│&&     └│OR
                         │OR─────A*B+B*C
    B───────────│&&     ┌│OR
                │&&─────┘
    C───────────│&&    

우승자

우승자는 5 일 동안 가장 많은 투표를 한 답변입니다.


1
인쇄 가능한 ASCII 문자는 95 자 뿐이며 다음을 포함하지 않습니다 ─ │ ┌ ┐ └ ┘. MS-DOS 문자 집합을 참조한다고 생각합니다 . 또한 예 B에서 두 개의 AND 게이트 사이에 단일 입력 분할 이 없어야 합니까? 그리고 우리는 와이어가 어디에서나 교차 할 필요가 없다고 가정 할 수 있습니까?
r3mainer

2
"ASCII 아트를 엄격히 표현"이라고 말하는 방식이 마음에 들며 ASCII가 아닌 문자 집합을 사용해야합니다.
Kendall Frey

@squeamishossifrage ascii 차트를 확장 한 후 128 ASCII 문자와 256 문자가 있다고 생각합니다. juniper.net/techpubs/en_US/idp5.1/topics/reference/general/…
Mukul Kumar

@squeamishossifrage : 아니오, 일부 확장 ASCII 문자 를 나타냅니다 . 명확히하기 위해 질문을 편집했습니다. 확장 ASCII에는 모든 7 비트 ASCII 문자와 다른 문자가 포함됩니다.
ProgramFOX

1
상자 그리기 문자를 사용해야한다는 점을 감안할 때와 같이 연결하는 ─│것이 이상해 보입니다 ─┤.
피터 테일러

답변:


16

C ++ 11

마침내 끝났다. 그리고 그것은 단지 하루 종일 걸렸습니다.

코드와 샘플 출력을 나열하기 전에 몇 가지 간단한 참고 사항 :

이 프로그램이 지원하는 것들

  • 각각의 수에 제한없이 입력
  • 입력 재사용
  • 하나의 입력 만 존재할 때 AND / OR 게이트 표현 생략
  • 코드 페이지 437 라인 드로잉 문자와 7 비트 ASCII 친화적 문자 모두 사용 (-DCP437 또는 컴파일러와 동등한 코드 페이지 437 지원에 해당)

이 프로그램이 지원하지 않는 것

  • 괄호로 묶기 (진실하게?)
  • 여러 NOTing
  • 일반 ASCII 공간이 아닌 모든 공백
  • 적절한 골프화 (영의 모든 의견을 제거했지만)
  • Sane 코딩 방법
  • 입력 파싱 코드와 눈을 마주 치기
  • 이식 가능한 유니 코드 선 그리기 문자 렌더링 로직이 2 차원 char버퍼를 "다운"할 수 있기 때문에 유니 코드를 지원할 수 없었습니다 .

암호

#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <set>
#include <map>
#include <valarray>
#include <cmath>

using namespace std;

vector<string> split(const string str, const string delim)
{
    vector<string> v;

    set<char> d;
    for (char c : delim) d.insert(c);

    string current {};
    for (char c : str)
    {
        if (d.find(c) != d.end())
        {
            v.push_back(current);
            current = "";
        }
        else
        {
            current += c;
        }
    }
    v.push_back(current);

    return v;
}

using Input = string;
struct TermInput
{
    Input name;
    int ypos;
    bool neg;
};
using Term = vector<TermInput>;
using Expr = vector<Term>;

#ifdef CP437
constexpr char VERT    = '\xB3';
constexpr char HORIZ   = '\xC4';
constexpr char RBRANCH = '\xC3';
constexpr char LUP     = '\xD9';
constexpr char LDOWN   = '\xBF';
constexpr char RUP     = '\xC0';
constexpr char RDOWN   = '\xDA';
#else
constexpr char VERT    = '|';
constexpr char HORIZ   = '-';
constexpr char RBRANCH = '}';
constexpr char LUP     = '\'';
constexpr char LDOWN   = '.';
constexpr char RUP     = '`';
constexpr char RDOWN   = ',';
#endif

string repeat(string s, int n)
{
    stringstream ss;
    for (int i = 0; i < n; i++)
    {
        ss << s;
    }

    return ss.str();
}
string repeat(char c, int n)
{
    stringstream ss;
    for (int i = 0; i < n; i++)
    {
        ss << c;
    }

    return ss.str();
}

enum class Direction
{
    RIGHT,
    DOWN
};

void matrixPut(char *matrix, int h, int w, int x, int y, const string s, Direction dir)
{
    if (x >= w || y >= h)
    {
        stringstream ss;
        ss << "matrixPut: point (" << x << ", " << y << ") out of matrix bounds!";
        throw new out_of_range(ss.str());
    }

    char *ins = matrix + (y * w) + x;
    char *end = matrix + (h * w);
    for (char c : s)
    {
        if (ins >= end) break;
        *ins = c;

        if (dir==Direction::RIGHT)
        {
            ins++;
        }
        else
        {
            ins += w;
        }
    }
}

void matrixPrint(char *matrix, int h, int w)
{
    for (int i = 0; i < (h * w); i++)
    {
        cout << matrix[i];
        if ((i+1)%w == 0) cout << endl;
    }
}

int main (int argc, char *argv[])
{
    string expression;

    if (argc == 1)
    {
        cout << "Enter expression:" << endl;
        getline(cin, expression);
    }
    else
    {
        expression = argv[1];
    }

    expression.erase(remove(expression.begin(), expression.end(), ' '), expression.end());

    Expr expr {};
    auto inputs = set<Input>();
    auto termInputs = multimap<Input, TermInput>();

    int inputYPos = 0;

    auto e = split(expression, "+");
    for (string term : e)
    {
        Term currTerm {};

        auto t = split(term, "*");
        for (string in : t)
        {
            bool neg = false;
            if (in.back() == '\'')
            {
                in.pop_back();
                neg = true;
            }

            Input currInput {in};
            inputs.insert(currInput);

            TermInput ti {currInput, inputYPos, neg};
            currTerm.push_back(ti);

            termInputs.insert(pair<Input, TermInput>{in, ti});
            inputYPos++;
        }

        expr.push_back(currTerm);
        inputYPos++;
    }


    int height = inputs.size() + termInputs.size() + expr.size() - 1;

    int width = 0;

    width += max_element(inputs.begin(), inputs.end(), [](Input a, Input b){ return a.length() < b.length(); })->length() + 2;
    int inputWidth = width;
    width += inputs.size()*2;

    int notAndStart = width;

    width += 7;
    width += expr.size()+1;

    int orStart = width;

    width += 4;

    width += 4;

    width += expression.length();

    char matrix[height * width];
    for (int i = 0; i < height*width; i++) matrix[i] = ' ';

    int  baseY = inputs.size();

    {
        int x = width - 4 - expression.length();
        int y = baseY + ((height-baseY) / 2);
        matrixPut(matrix, height, width, x, y, repeat(HORIZ, 4) + expression, Direction::RIGHT);
    }

    {
        int x = orStart;
        int y = baseY + (height-baseY)/2 - expr.size()/2;

        if (expr.size() == 1)
        {
            matrixPut(matrix, height, width, x, y, repeat(HORIZ, 4), Direction::RIGHT);
        }
        else {
            matrixPut(matrix, height, width, x  , y, repeat(HORIZ, expr.size()), Direction::DOWN);
            matrixPut(matrix, height, width, x+1, y, repeat(VERT , expr.size()), Direction::DOWN);
            matrixPut(matrix, height, width, x+2, y, repeat('O'  , expr.size()), Direction::DOWN);
            matrixPut(matrix, height, width, x+3, y, repeat('R'  , expr.size()), Direction::DOWN);
        }
    }

    {
        int x = notAndStart;
        int y = baseY;
        for (Term t : expr)
        {
            string layer[7];
            for (TermInput ti : t)
            {
                layer[0] += HORIZ;
                layer[1] += (ti.neg ? '>' : HORIZ);
                layer[2] += (ti.neg ? 'o' : HORIZ);
                layer[3] += HORIZ;
                layer[4] += (t.size() > 1 ? VERT : HORIZ);
                layer[5] += (t.size() > 1 ? '&' : HORIZ);
                layer[6] += (t.size() > 1 ? '&' : HORIZ);
            }

            for (int i = 0; i < 7; i++)
            {
                matrixPut(matrix, height, width, x+i, y, layer[i], Direction::DOWN);
            }

            y += t.size() + 1;
        }
    }

    {
        int x = 0;
        int y = 0;

        for (Input i : inputs)
        {
            string str = i + ": ";
            str += repeat(HORIZ, inputWidth - str.length());

            matrixPut(matrix, height, width, x, y, str, Direction::RIGHT);

            y++;
        }
    }

    {
        int x = inputWidth;
        int num = 0;
        int offset = inputs.size() * 2 - 1;

        for (Input in : inputs)
        {
            int y = 0;
            int len = inputs.size() * 2 - 1;
            auto it = inputs.find(in);
            while (it != inputs.begin())
            {
                it--;
                y++;
                len -= 2;
            }
            matrixPut(matrix, height, width, x, y, repeat(HORIZ, len) + LDOWN, Direction::RIGHT);
        }

        for (Input in : inputs)
        {
            auto yBreakRange = termInputs.equal_range(in);
            valarray<int> yBreaks(termInputs.count(in));
            int idx = 0;
            for (auto ti = yBreakRange.first; ti != yBreakRange.second; ti++)
            {
                yBreaks[idx++] = baseY + ti->second.ypos;
            }

            for (int y : yBreaks)
            {
                matrixPut(matrix, height, width, x+offset, y, repeat(HORIZ, inputs.size()*2 - offset), Direction::RIGHT);
            }

            int y = num + 1;
            int maxBreak = yBreaks.max();
            string branch = repeat(VERT, maxBreak - y + 1);

            for (int i : yBreaks)
            {
                branch[i-y] = RBRANCH;
            }
            branch.back() = RUP;

            matrixPut(matrix, height, width, x+offset, y, branch, Direction::DOWN);

            offset -= 2;
            num++;
        }
    }

    {
        int x = notAndStart + 7;
        int outY = baseY + (height-baseY)/2 - expr.size()/2;
        int breakx = expr.size()/2;

        for (Term t : expr)
        {
            int inY = baseY + (t.front().ypos + t.back().ypos) / 2;

            matrixPut(matrix, height, width, x, inY, repeat(HORIZ, abs(breakx)+1), Direction::RIGHT);

            matrixPut(matrix, height, width, x+abs(breakx)+1, outY, repeat(HORIZ, expr.size()-abs(breakx)), Direction::RIGHT);

            if (inY < outY)
            {
                string branch = LDOWN + repeat(VERT, outY-inY-1) + RUP;
                matrixPut(matrix, height, width, x+abs(breakx)+1, inY, branch, Direction::DOWN);
            }
            else if (inY > outY)
            {
                string branch = RDOWN + repeat(VERT, inY-outY-1) + LUP;
                matrixPut(matrix, height, width, x+abs(breakx)+1, outY, branch, Direction::DOWN);
            }

            outY++;
            breakx--;
        }
    }

    cout << endl;
    matrixPrint(matrix, height, width);
    cout << endl;
}

샘플 출력

$ ./gates "A'*B'+B*C"

A: -----.
B: ---. |
C: -. | |
    | | `->o-|&&--.
    | }--->o-|&&  `-|OR
    | |          ,--|OR----A'*B'+B*C
    | `------|&&-'
    `--------|&&

$ ./gates "A*B'*C+B*D'+F*C'*D+G*E*A'+F"

A: -------------.
B: -----------. |
C: ---------. | |
D: -------. | | |
E: -----. | | | |
F: ---. | | | | |
G: -. | | | | | |
    | | | | | | }----|&&
    | | | | | }--->o-|&&---.
    | | | | }--------|&&   |
    | | | | | | |          |
    | | | | | `------|&&--.|
    | | | }------->o-|&&  ||
    | | | | |   |         |`---|OR
    | }--------------|&&  `----|OR
    | | | | `----->o-|&&-------|OR----A*B'*C+B*D'+F*C'*D+G*E*A'+F
    | | | `----------|&&  ,----|OR
    | | |       |         |,---|OR
    `----------------|&&  ||
      | `------------|&&--'|
      |         `->o-|&&   |
      |                    |
      `--------------------'

샘플 출력 (CP437 사용)

A: ─────────────┐
B: ───────────┐ │
C: ─────────┐ │ │
D: ───────┐ │ │ │
E: ─────┐ │ │ │ │
F: ───┐ │ │ │ │ │
G: ─┐ │ │ │ │ │ │
    │ │ │ │ │ │ ├────│&&
    │ │ │ │ │ ├───>o─│&&───┐
    │ │ │ │ ├────────│&&   │
    │ │ │ │ │ │ │          │
    │ │ │ │ │ └──────│&&──┐│
    │ │ │ ├───────>o─│&&  ││
    │ │ │ │ │   │         │└───│OR
    │ ├──────────────│&&  └────│OR
    │ │ │ │ └─────>o─│&&───────│OR────A*B'*C+B*D'+F*C'*D+G*E*A'+F
    │ │ │ └──────────│&&  ┌────│OR
    │ │ │       │         │┌───│OR
    └────────────────│&&  ││
      │ └────────────│&&──┘│
      │         └─>o─│&&   │
      │                    │
      └────────────────────┘

4
순전히 독단적 결정을 위해 +10 :-)
r3mainer

그것은 내가 원하는 결과가 아니라, 당신의 노력에 대한 +1입니다 (개인적으로, 나는 그것을 고맙게 생각합니다).
Mukul Kumar

명성. CP437의 유무에 관계없이 매우 좋습니다.
Jonathan Van Matre

위의 피드백을 기반으로 게시물 (코드가 아닌)을 약간 수정했습니다. 또한 시스템에서 MinGW를 사용하여 기본 CP437 지원으로 빌드 할 수 있으므로 샘플 출력 형식을 추가했습니다.
curtmack

202 줄에서 VisualExpress에서 컴파일 오류가 발생합니다. int height 및 int width : Expression에는 상수 값이 있어야합니다. 또한 당신은 실종되었습니다#include <vector>
Jack Cole

5

C ++

휴! 1 일 12 시간 안에 완료했습니다 !!!
이 코드는 배열 만 처리합니다

입력 (유형)

  • SOP (제품 합계) 형식 만
  • 두 변수에 곱하는 항만 더함

    EXAMPLES :-
    
        A*B'+B*A+C*D  
    
        X*Y+Z'*A'*V*D+B*G+C'*A'  
    
  • 많은 수의 항, 변수를 처리 할 수 ​​있습니다.

    코드 :-

    #include<iostream>
    using namespace std;
    int main()
    {
    int i,j,k,l,m=0;
    char arr[80][80],expr[45];
    cout<<"enter the SOP(Sum Of products) expression : ";
    cin>>expr;
    cout<<"\n\n";
    for(i=0;expr[i]!='\0';i++)
    if(expr[i]=='*')m++;
    for(i=0;i<80;i++)
        for(j=0;j<80;j++)
            arr[i][j]=' ';
    for(i=0,j=0;i<80,expr[j]!='\0';j++)
    {
        if(expr[j]<=90&&expr[j]>=65||expr[j]<=122&&expr[j]>=97)
        {
            arr[i][0]=expr[j];
            i+=2;
        }
    }
    for(i=0,j=1;i<80;j++)
    {
        if(j==80){i++;j=0;}
        if(arr[i][j-1]<=90&&arr[i][j-1]>=65||arr[i][j-1]<=122&&arr[i][j-1]>=97)
        {
            for(k=0;k<7;k++)
                arr[i][j+k]=196;
            arr[i][j+k]=180;
        }
    }
    for(i=0,j=0;i<80;j++)
    {
        if(j==80){i++;j=0;}
        if(arr[i][j]==(char)180&&arr[i][j+1]==' ')
        {
            arr[i][j+1]=38;
        }
    }
    for(i=0,j=0,k=1;i<80;j++)
    {
        if(j==80){i++;j=0;}
        if(arr[i-1][j]==(char)180&&arr[i+1][j]==(char)180)
        {
            if(arr[i-1][j+1]==(char)38&&arr[i+1][j+1]==(char)38&&k)
            {
                arr[i][j]=179;arr[i][j+1]=38;
                for(l=2;l<4;l++)
                {
                    arr[i][j+l]=196;
                }
                k--;
            }
            else if(k==0)
            {
                k=1;
            }
        }
    }
    l=m;
    for(i=0,j=0;i<80;j++)
    {
        if(j==80){i++;j=0;}
        if(arr[i][j-1]==(char)196&&arr[i][j+1]==' '&&arr[i][j-2]==(char)38)
            {
            if(arr[i+3][j-2]==(char)38)
            {
                for(k=0;k<l;k++)
                    arr[i][j+k]=(char)196;
                arr[i][j+k-1]=(char)191;
    
                l--;
            }
            else
            {
                for(k=0;k<m;k++)
                arr[i][j+k]=(char)196;
            }
        }
    }
    for(i=0,j=0,k=1;i<80;j++)
    {
        if(j==80){i++;j=0;}
        if(arr[i][j]==(char)191&&arr[i][j-1]==(char)196)
        {
            for(;arr[i+k][j]==' ';k++)
            {
                arr[i+k][j]=(char)179;
            }
        k=1;
        }
    }
    for(i=0,j=0;i<80;j++)
    {
        if(j==80){i++;j=0;}
        if(arr[i][j]==(char)179&&arr[i][j-3]==(char)38&&arr[i+1][j]==(char)196)
        {
            arr[i][j]=(char)192;
            for(k=1;arr[i-k][j+k]==(char)179;k++)
            {
                arr[i-k][j+k]=(char)192;
            }
        }
    }
    for(i=0,j=0;i<80;j++)
    {
        if(j==80){i++;j=0;}
        if(arr[i][j-1]==(char)192)
        {
            for(k=0;arr[i][j+k]!=' ';k++)
                arr[i][j+k]=(char)196;
        }
    }
    for(i=0,j=0;i<80;j++)
    {
        if(j==80){i++;j=0;}
        if(arr[i][j-1]==(char)192&&arr[i][j]==' '||arr[i][j-1]==(char)196&&arr[i][j]==' ')
        {
            arr[i][j]=(char)180;
            arr[i][j+1]='O';
            arr[i][j+2]='R';
        }
    }
    for(i=0,j=0;i<80;j++)
    {
        if(j==80){i++;j=0;}
        if(arr[i][j-1]=='R'&&arr[i+1][j-1]==' ')
        {
            for(k=0;k<3;k++)
                arr[i][j+k]=(char)196;
            j+=k;
            for(k=0;expr[k]!='\0';k++)
            {
                arr[i][j+k]=expr[k];
            }
        }
    }
    for(i=0,k=0;i<80,expr[k]!='\0';k++)
    {
        if((expr[k]<='z'&&expr[k]>='a'||expr[k]<='Z'&&expr[k]>='A'))
        {
            if(expr[k+1]=='\'')
                arr[i][1]='\'';
            i+=2;
        }
    }
    for(i=0,j=0;i<80;j++)
    {
        if(j==80){i++;j=0;}
        if(arr[i][j]=='\''&&arr[i][j+1]==(char)196)
        {
            arr[i][j+3]=(char)180;
            arr[i][j+4]=(char)62;
            arr[i][j+5]='o';
        }
    }
    for(i=0;i<35;i++)
    {
        for(j=0;j<80;j++)
            cout<<arr[i][j];
        cout<<'\n';
    }
    return 0;
    }  
    

산출

여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.