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.