Hình ảnh phương trình nghệ thuật Ascii


10

Đối phó với các phương trình trong trường hợp không có trình soạn thảo phương trình tốt là lộn xộn và khó chịu. Ví dụ: nếu tôi muốn thể hiện một tích phân và giải pháp của nó, nó có thể trông giống như thế này:

Tích phân [x ^ 3 e ^ (- mx ^ 2 b / 2), dx] = - ((2 + b m x ^ 2) / (b ^ 2 * e ^ ((b m x ^ 2) / 2) * m ^ 2))

Tại integrals.wolfram.com , đây được gọi là "mẫu đầu vào." Không ai thích nhìn thấy một phương trình trong "hình thức đầu vào." Cách lý tưởng để hình dung phương trình này sẽ là:

nhập mô tả hình ảnh ở đây

(Wolfram gọi đây là "hình thức truyền thống")

Đối với codegolf này, hãy viết một chương trình sẽ lấy một số phương trình ở "dạng đầu vào" làm đầu vào và trực quan hóa phương trình đó trong một biểu diễn ascii của "dạng truyền thống". Vì vậy, với ví dụ này, chúng ta có thể nhận được một cái gì đó như thế này:

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

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

Yêu cầu:

  1. Không xáo trộn, đơn giản hóa hoặc sắp xếp lại đầu vào theo bất kỳ cách nào. Kết xuất nó ở dạng chính xác giống như được mô tả bởi đầu vào.
  2. Hỗ trợ bốn phép toán cơ bản (+, -, *, /). Khi không nhân hai số liền kề, ký hiệu * được ngụ ý và nên được bỏ qua.
  3. Hỗ trợ cho hội nhập (như trong ví dụ trên) là không cần thiết. Có thể hỗ trợ đầu vào với các chức năng như Tích hợp [...] hoặc Sqrt [...] là một phần thưởng.
  4. Hỗ trợ các quyền hạn như trong ví dụ trên (gốc thứ n có thể được mô hình hóa bằng cách nâng lên công suất 1 / n).
  5. Dấu ngoặc thừa (như những người xung quanh mẫu số và tử số của phần lớn trong ví dụ trên) nên được bỏ qua.
  6. Biểu thức trong mẫu số và tử số của một phân số phải được căn giữa ở trên và dưới đường phân chia ngang.
  7. Bạn có thể chọn có bắt đầu một dòng mới hay không sau một dấu bằng. Trong ví dụ trên, một dòng mới được bắt đầu.
  8. Thứ tự các hoạt động phải giống hệt nhau trong đầu ra như trong đầu vào.

Một số ví dụ về đầu vào và đầu ra liên quan để kiểm tra giải pháp của bạn:

Đầu vào:

1/2 + 1/3 + 1/4

Đầu ra:

1   1   1
- + - + -
2   3   4

Đầu vào:

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

Đầu ra:

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

Đầu vào:

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

Đầu ra:

2
-
x
--
5
--
 2
4

Đầu vào:

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

Đầu ra:

    2 1/2
(3 x )

Câu hỏi của bạn thường phải có một thẻ thể hiện loại cuộc thi đó là gì. Tôi đã tự do thêm một vì bạn đã nói "codegolf" trong văn bản.
dmckee --- ex-moderator mèo con

3
Vấn đề này là quá mơ hồ để chơi golf. Bạn không nói những cấu trúc nào phải được hỗ trợ, hoặc chúng phải trông như thế nào. Chỉ cần hỗ trợ +, -, * và / là đủ? Sigma có phải được hỗ trợ không? Chữ Hy Lạp thì sao? Các giải pháp khả thi cho câu hỏi mà bạn đặt ra, nó có thể quá đa dạng về chức năng để so sánh với độ dài mã.
MtnViewMark

@MtnViewMark, tôi đã thêm một số "Yêu cầu" ... hãy cho tôi biết nếu bây giờ golf tốt hơn.
Ami

@Ami - vâng, nhiều lắm.
MtnViewMark

Tôi đồng ý với MtnViewMark, điều này dường như rất kết thúc mở và mơ hồ. Có lẽ bạn sẽ tốt hơn để giới hạn đầu vào và đầu ra trong một bộ thử nghiệm được xác định rõ ràng cho mục đích chơi gôn. Bạn đã thực hiện một tham chiếu thực hiện?
gnibbler

Câu trả lời:


10

Python 2, 1666 ký tự

Bố cục thực sự khá dễ dàng - đó là phân tích cú pháp đầu vào là một nỗi đau của hoàng gia. Tôi vẫn không chắc nó hoàn toàn chính xác.

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])

Đối với đầu vào lớn trong câu hỏi, tôi nhận được:

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

Dưới đây là một số trường hợp thử nghiệm khó khăn hơn:

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)

Điều cuối cùng là sai, một số lỗi ưu tiên trong trình phân tích cú pháp.


không nên là đường cơ sở của đối số tích phân được tập trung vào trung tâm sau tích phân? Hiện tại nó trông giống như một chỉ số cho tích phân.
Joey

Không khó để thay đổi, nhưng nó sẽ lãng phí một số không gian. Tôi hiện đang làm cho dấu tích phân chỉ đủ lớn để vượt qua đối số của nó (với mức tối thiểu cao 3).
Keith Randall

Slight golf: Sử dụng các tab thay vì không gian đôi.
Máy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.