アスキーアート方程式ビジュアライザ


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、これは、「入力フォーム」と呼ばれています。「入力フォーム」で方程式を見ることを好む人はいません。この方程式を視覚化する理想的な方法は次のとおりです。

ここに画像の説明を入力してください

(ウォルフラムはこれを「伝統的な形」と呼んでいます)

このコードゴルフでは、「入力形式」の方程式を入力として受け取り、その方程式を「従来の形式」の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. 4つの基本的な数学演算(+、-、*、/)をサポートします。隣接する2つの数値を乗算しない場合、*記号は暗示されるため、省略してください。
  3. 統合のサポート(上記の例に示されている)はサポートされていません必要ん。Integrate [...]やSqrt [...]などの関数で入力をサポートできることはボーナスです。
  4. 上記の例に示すように、累乗をサポートします(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 )

通常、質問には、それがどのような種類のコンテストかを表すタグが必要です。あなたがテキストで「コードゴルフ」と言ったので、私は1を自由に追加しました。
dmckee ---元モデレーターの子猫

3
この問題は曖昧すぎてコードゴルフにはなりません。サポートする必要のある構成や、それらがどのように見える必要があるかは言いません。+、-、*、および/をサポートするだけで十分でしょうか?シグマはサポートする必要がありますか?ギリシャ文字はどうですか?あなたが提起した質問に対する可能な解決策は、コード長について比較するには機能が多すぎる可能性があります。
MtnViewMark 2011

@MtnViewMark、私はいくつかの「要件」を追加しました...ゴルフが今より良いかどうか私に知らせてください。
亜美

@亜美-はい、たくさん。
MtnViewMark 2011

私はMtnViewMarkに同意します。これは非常にオープンエンドで曖昧なようです。おそらく、ゴルフの目的のために、入力と出力を明確に定義されたテストケースのセットに制限する方が良いでしょう。リファレンスの実装を行いましたか?
ニブラー

回答:


10

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

最後の1つは間違っており、パーサーにいくつかの優先エラーがあります。


積分引数のベースラインは、積分の後に中央揃えにしないでください。現在、積分の添え字のように見えます。
ジョーイ

変更するのは難しいことではありませんが、一部のスペースが無駄になります。私は現在、積分記号をその引数にまたがるのに十分な大きさにしています(最小値3で)。
キースランドール

わずかなゴルフ:ダブルスペースの代わりにタブを使用します。
CalculatorFeline
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.