아스키 아트 방정식 비쥬얼 라이저


10

좋은 방정식 편집기가없는 상태에서 방정식을 다루는 것은 지저분하고 불쾌합니다. 예를 들어, 적분과 그 솔루션을 표현하려면 다음과 같이 보일 수 있습니다.

적분 [x ^ 3 e ^ (-mx ^ 2 b / 2), dx] =-((2 + b m x ^ 2) / (b ^ 2 * e ^ ((b m x ^ 2) / 2) * m ^ 2))

에서 integrals.wolfram.com , 이것은 "입력 양식"이라고합니다. 아무도 "입력 형식"으로 방정식을보고 싶어하지 않습니다. 이 방정식을 시각화하는 이상적인 방법은 다음과 같습니다.

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

(Wolfram은 이것을 "전통적인 형태"라고 부릅니다)

이 코드 골프의 경우, "입력 형식"의 방정식을 입력으로 사용하고 "전통 형식"의 ASCII 표현으로 해당 방정식을 시각화하는 프로그램을 작성하십시오. 따라서이 예제에서는 다음과 같은 것을 얻을 수 있습니다.

       /\      3
       |      x
       | ------------  dx = 
       |       2
      \/   (m x  b)/2
          e

              2
     2 + b m x
-(-----------------)
            2
   2  (b m x )/2  2
  b  e           m

요구 사항 :

  1. 어떤 식 으로든 입력을 섞거나 단순화하거나 재 배열하지 마십시오. 입력에서 설명한 것과 정확히 같은 형식으로 렌더링하십시오.
  2. 네 가지 기본 수학 연산 (+,-, *, /)을 지원합니다. 두 개의 인접한 숫자를 곱하지 않으면 * 기호가 내포되므로 생략해야합니다.
  3. 통합에 대한 지원 (위의 예에 표시된대로)은 필요 하지 않습니다. Integrate [...] 또는 Sqrt [...]와 같은 기능으로 입력을 지원할 수 있다는 것은 보너스입니다.
  4. 위의 예에 표시된대로 지지력을 구합니다 (n / n은 1 / n 제곱을 올림으로써 모델링 할 수 있습니다).
  5. 중복 괄호 (위의 예에서 대분수의 분모와 분자 주위의 괄호와 같이)는 생략해야합니다.
  6. 분수의 분모와 분자의 표현은 수평 분할 선 위와 아래에 중심을 두어야합니다.
  7. 등호 뒤에 새 줄을 시작할지 여부를 선택할 수 있습니다. 위의 예에서 새 줄이 시작됩니다.
  8. 작업 순서는 출력에서 ​​입력과 정확히 동일해야합니다.

솔루션 테스트를위한 입력 및 관련 출력의 예 :

입력:

1/2 + 1/3 + 1/4

산출:

1   1   1
- + - + -
2   3   4

입력:

3x^2 / 2 + x^3^3

산출:

   2     3
3 x     3
---- + x   
 2

입력:

(2 / x) / (5 / 4^2)

산출:

2
-
x
--
5
--
 2
4

입력:

(3x^2)^(1/2)

산출:

    2 1/2
(3 x )

질문에는 일반적으로 어떤 종류의 컨테스트인지를 나타내는 태그가 있어야합니다. 텍스트에 "codegolf"라고 말했기 때문에 하나를 추가 할 자유를 얻었습니다.
dmckee --- ex-moderator 고양이

3
이 문제는 코드 골프가 되기에는 너무 성가신 일입니다. 어떤 구조를 지원해야하는지 또는 어떤 구조를 사용해야하는지 말하지 않습니다. +,-, * 및 / 만 지원하면 충분합니까? 시그마가 지원되어야합니까? 그리스 문자는 어떻습니까? 당신이 제기 한 질문에 대한 가능한 해결책은 코드 길이와 비교하기에는 기능이 너무 다양 할 수 있습니다.
MtnViewMark 2

@ MtnViewMark, 나는 "요구 사항"을 추가했습니다 ... 골프가 더 나은지 알려주세요.
Ami

@ 아미-예, 많이.
MtnViewMark

MtnViewMark에 동의합니다. 이것은 매우 개방적이고 모호한 것 같습니다. 아마도 골프 목적으로 입력과 출력을 잘 정의 된 테스트 케이스 세트로 제한하는 것이 좋습니다. 참조 구현을 했습니까?
gnibbler

답변:


10

파이썬 2, 1666 자

레이아웃은 실제로 매우 쉽습니다-그것은 왕의 고통 인 입력의 파싱입니다. 나는 그것이 완전히 정확하다는 것을 여전히 확신하지 못한다.

import re,shlex
s=' '
R=range

# Tokenize.  The regex is because shlex doesn't treat 3x and x3 as two separate tokens.  The regex jams a space in between.                                                 
r=r'\1 \2'
f=re.sub
x=shlex.shlex(f('([^\d])(\d)',r,f('(\d)([^\d])',r,raw_input())))
T=[s]
while T[-1]:T+=[x.get_token()]
T[-1]=s

# convert implicit * to explicit *                                                                                                                                          
i=1
while T[i:]:
 if(T[i-1].isalnum()or T[i-1]in')]')and(T[i].isalnum()or T[i]in'('):T=T[:i]+['*']+T[i:]
 i+=1

# detect unary -, replace with !                                                                                                                                            
for i in R(len(T)):
 if T[i]=='-'and T[i-1]in'=+-*/^![( ':T[i]='!'
print T

# parse expression: returns tuple of op and args (if any)                                                                                                                   
B={'=':1,',':2,'+':3,'-':3,'*':4,'/':4,'^':5}
def P(t):
 d,m=0,9
 for i in R(len(t)):
  c=t[i];d+=c in'([';d-=c in')]'
  if d==0and c in B and(B[c]<m or m==B[c]and'^'!=c):m=B[c];r=(c,P(t[:i]),P(t[i+1:]))
 if m<9:return r
 if'!'==t[0]:return('!',P(t[1:]))
 if'('==t[0]:return P(t[1:-1])
 if'I'==t[0][0]:return('I',P(t[2:-1]))
 return(t[0],)

# parenthesize a layout                                                                                                                                                     
def S(x):
 A,a,b,c=x
 if b>1:A=['/'+A[0]+'\\']+['|'+A[i]+'|'for i in R(1,b-1)]+['\\'+A[-1]+'/']
 else:A=['('+A[0]+')']
 return[A,a+2,b,c]

# layout a parsed expression.  Returns array of strings (one for each line), width, height, centerline                                                                      
def L(z):
 p,g=z[0],map(L,z[1:])
 if p=='*':
  if z[1][0]in'+-':g[0]=S(g[0])
  if z[2][0]in'+-':g[1]=S(g[1])
 if p=='^'and z[1][0]in'+-*/^!':g[0]=S(g[0])
 if g:(A,a,b,c)=g[0]
 if g[1:]:(D,d,e,f)=g[1]
 if p in'-+*=,':
  C=max(c,f);E=max(b-c,e-f);F=C+E;U=[s+s+s]*F;U[C]=s+p+s;V=3
  if p in'*,':U=[s]*F;V=1
  return([x+u+y for x,u,y in zip((C-c)*[s*a]+A+(E-b+c)*[s*a],U,(C-f)*[s*d]+D+(E-e+f)*[s*d])],a+d+V,F,C)
 if'^'==p:return([s*a+x for x in D]+[x+s*d for x in A],a+d,b+e,c+e)
 if'/'==p:w=max(a,d);return([(w-a+1)/2*s+x+(w-a)/2*s for x in A]+['-'*w]+[(w-d+1)/2*s+x+(w-d)/2*s for x in D],w,b+e+1,b)
 if'!'==p:return([' -  '[i==c::2]+A[i]for i in R(b)],a+2,b,c)
 if'I'==p:h=max(3,b);A=(h-b)/2*[s*a]+A+(h-b+1)/2*[s*a];return(['  \\/|/\\  '[(i>0)+(i==h-1)::3]+A[i]for i in R(h)],a+3,h,h/2)
 return([p],len(p),1,0)

print'\n'.join(L(P(T[1:-1]))[0])

질문에 큰 입력을 얻으려면 다음을 얻습니다.

 /\         2                     2 
 |     - m x  b          2 + b m x  
 |     --------    = - -------------
 |  3      2                    2   
\/ x  e         dx         b m x    
                           ------   
                        2     2    2
                       b  e       m 

좀 더 까다로운 테스트 사례는 다음과 같습니다.

I:(2^3)^4
O:    4
  / 3\ 
  \2 / 

I:(2(3+4)5)^6
O:             6
  (2 (3 + 4) 5) 

I:x Integral[x^2,dx] y
O:   /\ 2     
  x  | x  dx y
    \/        

I:(-x)^y
O:     y
  (- x) 

I:-x^y
O:     y
  (- x)

그 마지막 것은 잘못되었습니다. 파서의 우선 순위 오류입니다.


적분 인수의 기준이 적분의 중심에 위치해서는 안됩니까? 현재는 정수의 첨자처럼 보입니다.
Joey

변경하기는 어렵지만 공간이 낭비됩니다. 나는 현재 적분 부호가 논쟁의 여지가 될 정도로 충분히 커야한다 (최소 3 개).
Keith Randall

약간의 골프 : 이중 공백 대신 탭을 사용하십시오.
CalculatorFeline
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.