Tìm các bộ sau


14

Thử thách dưới đây đòi hỏi bạn phải làm quen với lý thuyết trình phân tích cú pháp chính thức. Nếu bạn không biết câu hỏi đang hỏi là gì vì bạn không biết các thuật ngữ này có nghĩa gì, ngữ pháp không ngữ cảnh và các bộ đầu tiên / theo dõi được đề cập trong rất nhiều khóa học đại học.

Tôi có thể giới thiệu khóa học Stanford này , đặc biệt là các tài liệu hướng dẫn 08 và 09 (từ trang 7). Tôi đã trích xuất cũng trích xuất một bảng cheat từ các tài liệu này - Tôi khuyên mọi người nên thử thách này để đọc nó .


Viết một chương trình hoặc hàm đưa ra một ngữ pháp không ngữ cảnh tìm thấy tập hợp theo sau của mọi nonterminal. Một cách không chính thức, tập hợp theo sau của nonterminal là một tập hợp các thiết bị đầu cuối và $(có nghĩa là đầu cuối) mà bạn có thể tìm thấy sau thiết bị đầu cuối đó trong một câu hợp lệ.

Đầu vào được đưa ra dưới dạng một chuỗi ASCII có thể in hoặc một dòng các dòng ASCII có thể in được. Bạn có thể xuất các bộ theo bất kỳ định dạng hợp lý nào, sử dụng $(dưới dạng đầu ra bằng chữ hoặc chuỗi bên trong một bộ, v.v.) để chỉ ra kết thúc của đầu vào. Bạn có thể cho rằng đầu vào luôn hợp lệ theo định dạng bên dưới.

Ngữ pháp miễn phí ngữ cảnh được đưa ra một cách rất đơn giản. Mỗi dòng chứa một sản xuất duy nhất. Mỗi sản xuất là một danh sách các biểu tượng phân tách không gian. Một thiết bị đầu cuối là một chuỗi các ký tự được bao quanh bởi dấu nháy đơn (ví dụ '**'). Để đơn giản, bạn có thể cho rằng các thiết bị đầu cuối không chứa khoảng trắng, nhưng sẽ rất tuyệt nếu chương trình của bạn cho phép. Một nonterminal có thể là bất kỳ chuỗi không chứa khoảng trắng hoặc $. Sản phẩm trống (thường được biểu thị bằng) chỉ đơn giản là một dòng chỉ chứa bên trái phía bên trái. Dòng đầu tiên là sản xuất xác định biểu tượng bắt đầu.

Ví dụ, ngữ pháp sau:

S → aSa | bSb | ε

Sẽ được đưa ra như:

S 'a' S 'a'
S 'b' S 'b'
S

Ví dụ đầu vào / đầu ra:

In:
S 'a' S 'a'
S 'b' S 'b'
S

Out:
S {'a', 'b', $}

In:
S A B C
A 'a'
A C 'b'
A
B C
B 'd' A
B
C 'e'
C 'f' 

Out:
S {$}
A {'d', 'e', 'f'}
B {'e', 'f'}
C {'b', 'e', 'f', $}

In:
Start Alice Bob
Alice Charlie 'a'
Alice
Bob Bob 'a' Alice Charlie
Bob '!!!'
Charlie 'b'
Charlie

Out:
Start {$}
Alice {'a', '!!!', 'b', $}
Bob {'a', $}
Charlie {'a', $}

Mã ngắn nhất trong byte thắng.


4
Giả sử rằng mọi người biết ngữ pháp miễn phí ngữ cảnh có vẻ tốt, nhưng tôi nghĩ nó sẽ không ảnh hưởng đến thách thức nếu bạn đưa vào định nghĩa của một bộ theo dõi ngay tại đây thay vì chỉ liên kết với nó.
Martin Ender

1
Điều này mang lại một số ký ức từ " Trình biên dịch xây dựng " tại trường đại học, nơi chúng tôi phải giải quyết rất nhiều nhiệm vụ tương tự.
insertusernamehere

Câu trả lời:


3

Perl, 257 byte

Bao gồm +4 cho -0p

Đưa ra ngữ pháp trên STDIN (không có dấu cách. Hãy đảm bảo xóa khoảng trắng thừa trong ví dụ thứ hai). Giả sử tên không phải thiết bị đầu cuối chỉ chứa chữ cái, chữ số và _. Sử dụng #thay vì $chỉ ra kết thúc đầu vào. Có thể xử lý các chữ có chứa khoảng trắng

perl -M5.010 follow.pl
E T e
e '+' T e
e
T F t
t '*' F t
t
F '(' E ')'
F 'id'
^D

Xuất ra các tập hợp sau dưới dạng một danh sách non-terminal literalkhông theo thứ tự cụ thể. Đối với ví dụ trên, nó xuất ra:

F ')'
F #
t ')'
t #
T ')'
T #
F '+'
t '+'
T '+'
F '*'
e ')'
e #
E ')'
E #

follow.pl:

#!/usr/bin/perl -0n
s/'.*?'/~$&/eg;s% (?=(\w.*\n))%$_.=">$1"%reg;/\s/;$_.=">$` #\n";s%^((\w+)\K ?\S*).*%$s{$1}++||"\$a.=s/ $2\\b/$&/rg"%eemgr,s%^(\w+ ).*?(\w+)$%"\$a.=s/>$1/>$2 /rg"%eermg,$_.=$a,s%>.*\xd8\K .*%%g,s%.+\n%$&x!/\n$&/g%eg until$$_++;s/\xd8.*?\xd8/~$&/eg;say/>(\w+ \W\S*\n)/g

Hoạt động như được hiển thị, nhưng thay thế \xd8\nbằng các phiên bản nghĩa đen của chúng để có được số điểm yêu cầu.

Có thể cải thiện điều này vì việc chuyển đổi các firstbộ thành các followbộ hiện đang rất khó xử.

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.