ASCII Sanat Denklemi Görüntüleyici


10

İyi bir denklem düzenleyicisinin yokluğunda denklemlerle uğraşmak dağınık ve tatsızdır. Örneğin, bir integral ve çözümünü ifade etmek istersem, şöyle görünebilir:

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

At integrals.wolfram.com , bu "Giriş formu" adı verilir. Hiç kimse "giriş formunda" bir denklem görmeyi sevmez. Bu denklemi görselleştirmenin ideal yolu:

resim açıklamasını buraya girin

(Wolfram buna "geleneksel form" diyor)

Bu codegolf için, girdi olarak "girdi formu" nda bazı denklemleri alacak bir program yazın ve bu denklemi "geleneksel biçim" in ascii temsili ile görselleştirin. Yani, bu örnek için şöyle bir şey alabiliriz:

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

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

Gereksinimler:

  1. Girişi herhangi bir şekilde karıştırmayın, basitleştirmeyin veya yeniden düzenlemeyin. Giriş tarafından açıklananla aynı şekilde işleyin.
  2. Dört temel matematik işlemini (+, -, *, /) destekleyin. İki bitişik sayıyı çarpmadığınızda * sembolü ima edilir ve atlanmalıdır.
  3. Entegrasyon desteği (yukarıdaki örnekte gösterildiği gibi) gerekli değildir . Integrate [...] veya Sqrt [...] gibi işlevlerle girişi destekleyebilmek bir bonus.
  4. Yukarıdaki örnekte gösterildiği gibi destek güçleri (n'inci kök, 1'inci güce yükseltilerek modellenebilir).
  5. Fazlalıklı parantez (yukarıdaki örnekte büyük payın paydası ve payının etrafındaki gibi) atlanmalıdır.
  6. Bir kesirin payda ve payındaki ifade, yatay bölme çizgisinin üstünde ve altında ortalanmalıdır.
  7. Eşittir işaretinden sonra yeni bir satıra başlayıp başlamayacağınızı seçebilirsiniz. Yukarıdaki örnekte, yeni bir satır başlatılır.
  8. İşlem sırası, çıktıda giriş ile aynı olmalıdır.

Çözümünüzü test etmek için bazı girdi ve ilişkili çıktı örnekleri:

Giriş:

1/2 + 1/3 + 1/4

Çıktı:

1   1   1
- + - + -
2   3   4

Giriş:

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

Çıktı:

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

Giriş:

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

Çıktı:

2
-
x
--
5
--
 2
4

Giriş:

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

Çıktı:

    2 1/2
(3 x )

Sorunuz genellikle ne tür bir yarışma olduğunu belirten bir etikete sahip olmalıdır. Bir tane ekleme özgürlüğünü aldım çünkü metinde "codegolf" dedin.
dmckee --- ex-moderatör kedi yavrusu

3
Bu sorun kod-golf olamayacak kadar belirsiz. Hangi yapıların desteklenmesi gerektiğini ya da neye benzemeleri gerektiğini söylemezsiniz. Sadece +, -, * ve / veya yeterli olur mu? Sigma desteklenmeli mi? Yunan harfleri ne olacak? Sorunuza yönelttiğiniz soruya olası çözümler, kod uzunluğu için karşılaştırılamayacak kadar işlevsel olabilir.
MtnViewMark

@MtnViewMark, bazı "Gereksinimler" ekledim ... golf şimdi daha iyi olup olmadığını bana bildirin.
Ami

@Ami - evet, çok.
MtnViewMark

MtnViewMark'a katılıyorum, bu çok açık uçlu ve belirsiz görünüyor. Belki de golf amacıyla girdi ve çıktıyı iyi tanımlanmış test senaryolarıyla sınırlamak daha iyi olur. Referans uygulaması yaptınız mı?
gnibbler

Yanıtlar:


10

Python 2, 1666 karakter

Yerleşim aslında oldukça kolay - kraliyet ağrısı olan girdinin ayrıştırılması. Hala tamamen doğru olduğundan emin değilim.

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

Sorudaki büyük girdi için şunu alıyorum:

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

İşte biraz daha zor test örnekleri:

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)

Bu sonuncusu yanlış, ayrıştırıcıda bazı öncelik hataları.


integral argümanının temel çizgisinin integralden sonra dikey olarak merkezlenmesi gerekmez mi? Şu anda integral için bir alt simge gibi görünüyor.
Joey

Değiştirmesi zor değil, ama biraz yer harcar. Şu anda integral işaretini argümanı kapsayacak kadar büyük yapıyorum (en az 3 yüksek).
Keith Randall

Hafif golf: Çift boşluk yerine sekme kullanın.
CalculatorFeline
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.