LaTeX của người nghèo


37

Bạn được vận chuyển trong một vũ trụ song song nơi mọi người viết các phương trình toán học trên máy tính dưới dạng nghệ thuật ASCII bằng tay. Là một người nghiện LaTeX, điều này là hoàn toàn không thể chấp nhận được và bạn nên tự động hóa quá trình này một chút.

Mục tiêu của bạn là viết một chương trình đưa ra phiên bản ASCII của phương trình được nhập dưới dạng lệnh toán LaTeX.

Các lệnh LaTeX bắt buộc phải hỗ trợ

  • Tổng: lệnh LaTeX cho một khoản tiền là \sum_{lower bound}^{upper bound}

    Con số ASCII bạn phải sử dụng cho các khoản tiền là:

    upper bound
        ___ 
        \  `
        /__,
    lower bound
    
  • Sản phẩm: lệnh LaTeX cho sản phẩm là \prod_{lower bound}^{upper bound}

    Con số ASCII bạn phải sử dụng cho các sản phẩm là:

    upper bound
        ____
        |  |
        |  |
    lower bound
    
  • Phân số: lệnh LaTeX cho phân số là \frac{numerator}{denominator}

    Con số ASCII bạn phải sử dụng cho các phân số là:

     numerator
    -----------
    denominator
    

Bất cứ điều gì không phải là một trong ba lệnh đó đều được hiển thị. Ví dụ, \sum{i=3}^{e^10}\frac{3x+5}{2}nên được hiển thị dưới dạng

e^10
___  3x+5
\  ` ----
/__,  2
i=3

Đầu vào

Đầu vào là một lệnh LaTeX được truyền dưới dạng một chuỗi (hoặc ngôn ngữ của bạn tương đương với chuỗi). Các lệnh LaTeX có thể được lồng nhau, ví dụ \frac{\frac{1}{2}}{3}là một đầu vào hợp lệ. Các đầu vào được cho là luôn luôn chính xác (không cần kiểm tra cú pháp của LaTeX trong mã của bạn). Các đầu vào sẽ chỉ bao gồm ba lệnh LaTeX được trình bày ở trên và 'văn bản' mà bạn sẽ không cần định dạng.

Các lệnh LaTeX sẽ luôn đi kèm với cú pháp được trình bày ở trên, tức là các tổng và sản phẩm sẽ luôn có giới hạn trên và dưới (mặc dù chúng có thể trống) và sẽ luôn có một tử số và mẫu số cho các phân số.

Chúng tôi giả định rằng giới hạn của tổng và sản phẩm dài tối đa 4 ký tự (= chiều rộng của ký hiệu tổng và sản phẩm), do đó bạn không phải lo lắng về các vấn đề chồng chéo có thể xảy ra. Vì những lý do tương tự, chúng tôi giả định rằng giới hạn chỉ là 'văn bản' và sẽ không bao giờ là lệnh LaTeX, ví dụ: \sum_{\sum_{1}^{2}}^{1}không phải là đầu vào hợp lệ.

Đầu ra

Đầu ra của chương trình của bạn là đại diện ASCII của lệnh LaTeX mà bạn được cung cấp làm đầu vào.

Chương trình của bạn phải tính đến căn chỉnh ngang: ví dụ: giới hạn của tổng hoặc sản phẩm phải được căn chỉnh theo chiều ngang với ký hiệu tổng hoặc sản phẩm (có cả 4 ký tự). Nếu ràng buộc có số lượng ký tự lẻ, việc nó là một ký tự ở bên phải hay bên trái của trung tâm, không có vấn đề gì. Dòng của phân số phải dài bằng tử số hoặc mẫu số, tùy theo giá trị nào dài nhất.

Chương trình của bạn phải đưa sự liên kết dọc vào tài khoản: ví dụ, \frac{\frac{1}{2}}{3} = \frac{1}{6}nên được hiển thị dưới dạng

1
-
2   1
- = -
3   6

Đối với các khoản tiền và sản phẩm, vì các ký hiệu cao 4 ký tự, trung tâm dọc được coi là dòng thứ hai từ trên xuống.

Khoảng cách ngang được coi là chính xác trong đầu vào đã cho, tức là khoảng trắng trong đầu vào sẽ được hiển thị trong đầu ra.

Các trường hợp thử nghiệm

  • Đầu vào abc = 2

    Đầu ra abc = 2

  • Đầu vào e = \sum_{n=0}^{+inf} \frac{1}{n!}

    Đầu ra

        +inf
        ___  1
    e = \  ` --
        /__, n!
        n=0
    
  • Đầu vào e^x = 1 + \frac{x}{1 - \frac{x}{2 + x - ...}}

    Đầu ra

                     x
    e^x = 1 + ---------------
                       x
              1 - -----------
                  2 + x - ...
    
  • Đầu vào \prod_{i=1}^{n} \frac{\sum_{j=0}^{m} 2j}{i + 1}

    Đầu ra

           m
          ___
          \  ` 2j
     n    /__,
    ____  j=0
    |  |  -------
    |  |   i + 1
    i=1
    
  • Đầu vào \frac{sum}{prod} = \sum_{frac}^{prod} sum

    Đầu ra

           prod
    sum    ___
    ---- = \  ` sum
    prod   /__,
           frac
    

Chấm điểm

Đây là , vì vậy mã ngắn nhất sẽ thắng.


11
Thử thách đầu tiên tốt đẹp. Có vẻ khá khó khăn; Tôi rất vui khi thấy một số giải pháp.
Alex A.

1
@Alex A. Ban đầu tôi dự định cũng có tích phân, căn bậc hai và dấu ngoặc đơn có thể mở rộng, nhưng điều đó có vẻ hơi quá ...
Fatalize

2
Tôi tin rằng sẽ có trường hợp bạn bị chồng chéo. Ví dụ: nếu bạn có một tổng trong đó thuật ngữ trở nên cao hơn 4 (ví dụ: nhiều phân số, phân số của tổng) và tổng có giới hạn trên / dưới dài, chuỗi giới hạn trên / dưới có thể trùng với thuật ngữ. Làm thế nào điều đó sẽ được giải quyết? Có phải thuật ngữ phải được đặt cách nhau từ tổng để tránh trùng lặp với giới hạn?
Reto Koradi


8
Tôi thực sự hy vọng ai đó đưa ra giải pháp trong LaTeX
Shadowtalker

Câu trả lời:


23

Con trăn 2 656 627 618 byte

M=max
O=lambda l,o=2:[(p+o,c)for p,c in l]
def C(s,m=0):
 if''<s<'}'[m:]:f,w,h,d,s=C(s,1);F,W,H,D,s=C(s);e=M(d,D);return[O(f,e-d)+O(F,w*1j+e-D),w+W,M(h-d,H-D)+e,e,s]
 if'\\'!=s[:1]:return[[(0,s[:1])]*m,m,m,0,s[1:]]
 t=s[1]<'s';e=s[1]>'f';f,w,h,d,s=C(s[5+t+e:]);F,W,H,D,s=C(s[1+e:]);g=M(w,W);G=C('-'*g)[0]
 if e:f,w,h,F,W,H=F,W,H,f,w,h;g=4;p=C('|  |')[0];G=C('_'*(3+t))[0]+[O(C('/__,')[0])+[(1,'\\'),(1+3j,'`')],O(p,1)+O(p)][t]
 x=M(w,W,g);return[O(f,(x-w)/2*1j)+O(F,(x-W)/2*1j+h+3**e)+O(G,(x-g)/2*1j+h),x,h+3**e+H,h+e,s]
f,w,h,d,s=C(raw_input())
for y in range(h):print"".join(dict(f).get(y+x*1j,' ')for x in range(w))

Đưa đầu vào vào STDIN và ghi đầu ra vào STDOUT.

Chương trình giả định rằng không có chuỗi điều khiển nào khác hơn \frac, \sumhoặc \prodxuất hiện trong đầu vào (nghĩa là nó sẽ không hiển thị dưới dạng văn bản bình thường) và nó ~cũng không xuất hiện (dù sao nó cũng có ý nghĩa đặc biệt trong chế độ toán học .) mặt khác, chương trình không hỗ trợ các công thức tùy ý làm giới hạn cho \sum\prod.

Giải trình

Nó hoạt động giống như TeX! (tốt, sắp xếp ...) Mỗi ​​biểu mẫu con (bắt đầu từ các ký tự đơn và xây dựng các công thức phức tạp hơn) được chuyển thành một hộp, với chiều rộng, chiều cao và chiều sâu liên quan (đường cơ sở). Các hộp có công thức đơn giản hơn được kết hợp thành các hộp lớn hơn để tạo thành các công thức phức tạp, v.v. Nội dung của mỗi hộp được thể hiện dưới dạng danh sách các cặp vị trí / ký tự, liên quan đến góc trên cùng bên trái của hộp; khi các hộp được kết hợp thành một hộp lớn hơn, các vị trí được bù theo vị trí tương đối của các hộp nhỏ hơn bên trong hộp lớn hơn và các danh sách được nối với nhau.

Cuối cùng, chúng tôi kết thúc với một hộp cấp cao nhất, được chuyển đổi thành một hình thức có thể in được.


Để thêm gia vị một chút, phiên bản sau đây cũng hỗ trợ căn bậc hai:

Ví dụ:

  • \frac{-b +- \sqrt{b^2 - 4ac}}{2a}

            _________
    -b +- \/b^2 - 4ac
    -----------------
           2a
    
  • |v| = \sqrt{ \sum_{i}^{} v[i]^2 }

               _____________
              / ___
    |v| =    /  \  ` v[i]^2
            /   /__,
          \/     i
    

9
Tôi phải nói rằng tôi rất ấn tượng! Đã thử chạy \prod_{i=1}^{\sum_{azededzeda}^{k}} \frac{\sum_{j=0}^{m} 2j}{i + 1}và nó xuất ra mọi thứ một cách chính xác mà không bị trùng lặp, mặc dù điều đó không bắt buộc. Tốt đẹp!
Gây tử vong

4
Và bạn hỗ trợ căn bậc hai chỉ với ~ 18% byte. Ai đó ngăn người đàn ông này lại!
Gây tử vong vào

1
@Ell Điều đó có ý nghĩa! Làm tốt lắm :)
Kade

22

LaTeX, 540 535 ký tự

Tuyên bố từ chối trách nhiệm: Điều này không hoàn hảo và được cho là không được coi là một câu trả lời hợp lệ.

\ usepackage [LGRgalet] {mathastext}
\ refreshcommand {\ sum} {\ kern-1ex \ displaystyle \ mathop {\ vph Phantom {\ int} \ started {mảng} {l} \ mbox {\ underline {\ hspace {12pt}}} \ \ mbox {\ textbackslash } \ hspace {8pt} `\\\ mbox {/ \ underline {\ hspace {8pt}},} \ end {mảng}} \ displaylimits}
\ đổi mới {\ prod} {\ kern-1ex \ displaystyle \ mathop {\ vph Phantom {\ int} \ started {mảng} {c} \ mbox {\ underline {\ hspace {16pt}}} | \ | \ \ \ \ | \ end {mảng}} \ displaylimits}
\ refreshcommand {\ frac} [2] {\ mathop {\ xleaders \ hbox {-} \ hfill \ kern0pt} \ giới hạn ^ {# 1} _ {# 2}}
\ DeclareMathSizes {10} {10} {10} {10}

Một số trợ giúp từ @Firthize, xem ý kiến ​​để biết chi tiết.

Kiểm tra:

Đầu vào: \prod_{i=1}^{n} \frac{\sum_{j=0}^{m} 2j}{i + 1}

Đầu ra:

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

Như bạn có thể thấy, đầu ra không chính xác theo thông số kỹ thuật. Điều này có thể không đủ điều kiện cho câu trả lời của tôi, nhưng tôi vẫn nghĩ rằng nó đáng để đăng.

Tôi đã viết điều này trên sharelatex.com. Bạn có thể chơi với nó ở đây .


1
Tốt đẹp! Tôi đã chơi với mã của bạn một chút và tôi nghĩ rằng bạn có thể sửa mọi thứ bằng cách thay đổi phân số của mình thành \newcommand{\frac}[2]{\mathop{\xleaders\hbox{-}\hfill\kern0pt}\limits^{#1}_{#2}}, thêm vào \DeclareMathSizes{10}{10}{10}{10}sau đó (để ngăn LaTeX thu nhỏ tử số và mẫu số) và bằng cách thêm \kern-1extrước \displaystylevào định nghĩa tổng và sản phẩm của bạn.
Gây tử vong vào
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.