Perl -a
→ Máy I / D , 24 byte
$p=$a[$p]+=$_ for@F;redo
Hãy thử trực tuyến! (chứa một tiêu đề in trạng thái bên trong và tạm dừng sau 10 lần lặp, để hành vi có thể quan sát được)
Về ngôn ngữ
Tôi đã dành vài ngày qua để làm việc trên máy I / D , một trong những ý tưởng mới nhất của tôi cho các ngôn ngữ lập trình rất đơn giản. Nó hoạt động như sau: bộ lưu trữ dữ liệu bao gồm RAM không giới hạn, ban đầu là tất cả các số không. Mỗi phần tử có thể lưu trữ một số nguyên không giới hạn (mặc dù trong thực tế, hầu hết các chương trình máy I / D sẽ chỉ lưu trữ các số nguyên nhỏ trong hầu hết chúng và chỉ sử dụng các số nguyên không giới hạn như một cách giải quyết các ô có địa chỉ lớn). Ngoài ra còn có một con trỏ dữ liệu, trỏ đến một ô (tức là giữ địa chỉ dưới dạng một ô); ban đầu nó cũng bằng không.
Chỉ có hai lệnh:
I
: Tăng ô mà con trỏ dữ liệu trỏ tới. (Con trỏ dữ liệu vẫn không thay đổi.)
D
: Dereference con trỏ dữ liệu, tức là đọc giá trị của ô mà con trỏ dữ liệu trỏ đến. Sau đó lưu trữ giá trị kết quả mà bạn đọc lại vào con trỏ dữ liệu.
Thực thi chỉ đơn giản là chạy chương trình trong một vòng lặp liên tục, mãi mãi.
Thật đáng ngạc nhiên khi một ngôn ngữ đơn giản này là Turing-Complete, vì vậy tôi đã nghiên cứu để chứng minh điều đó. Đây là bằng chứng . Nó khá giống với (nhưng đơn giản hơn) bằng chứng cho Lập trình viên ba sao, một ngôn ngữ rất giống nhau (và trên thực tế, bài nộp này sử dụng cùng một "vỏ" OISC cơ bản xung quanh chương trình, chỉ khác với hướng dẫn thực tế được triển khai).
Về chương trình
Sử dụng
Đầu vào phải được cung cấp trên đầu vào tiêu chuẩn và là chương trình máy I / D không có nhận xét và sử dụng cú pháp RLE / OISC. (Máy I / D có hai cú pháp tương đương, khác nhau, nhưng đối với tính golf, chương trình này chỉ hỗ trợ một trong số chúng.) Trong cú pháp này, một chương trình là một chuỗi các số thập phân, biểu thị độ dài của các I
lệnh giữa D
các lệnh. (Bạn có thể chỉ định hai hoặc nhiều D
lệnh liên tiếp bằng cách đặt "chạy 0 I
lệnh" giữa chúng, vì vậy cú pháp hoàn toàn chung.)
Giải trình
Như có thể thấy từ chương trình, điều này không thực hiện riêng lẻ I
và D
các lệnh. Trên thực tế, đó là một trình thông dịch tối ưu hóa (rất nhẹ) (hoàn toàn vì viết ngắn hơn theo cách này). Điều quan trọng là để thấy rằng một lệnh chạy n lệnh tăng làm tăng mục tiêu của con trỏ dữ liệu n lần, tức là thêm n vào nó; và việc chạy các lệnh tăng 0 cũng có thể được thực hiện theo cách này, vì việc thêm 0 vào bộ nhớ không có hiệu lực. Vì vậy, hoạt động chúng tôi thực sự thực hiện là xen kẽ giữa thực hiện một hoạt động I
và a D
. Hay nói cách khác, "thêm nđến giá trị được trỏ bởi con trỏ dữ liệu (lưu trữ lại giá trị được trỏ bởi con trỏ dữ liệu), sau đó đọc giá trị được trỏ bởi con trỏ dữ liệu và lưu trữ nó trong con trỏ dữ liệu ". để được, và chúng ta có thể đơn giản hóa hơn nữa để "thêm n vào giá trị được trỏ bởi con trỏ dữ liệu, sau đó lưu trữ giá trị đó cả trong mục tiêu của con trỏ dữ liệu và chính con trỏ dữ liệu".
Vì vậy, điều đó làm cho cốt lõi của chương trình của chúng tôi. Chúng tôi đang sử dụng một mảng $a
để lưu trữ RAM và $p
là con trỏ dữ liệu (lập chỉ mục vào mảng):
$p=$a[$p]+=$_
+ $_ add {the run length}
$a[$p] to the element of $a pointed to by $p
$a[$p] = storing the result back into that element
$p= and also in the pointer itself
Thuận tiện, Perl diễn giải các phần tử mảng chưa được xác định thành 0 khi chúng được coi như số, vì vậy mảng sẽ được khởi tạo một cách lười biếng thành số không cho chúng tôi mà không cần bất kỳ mã rõ ràng nào cho việc đó. (Một vấn đề tiềm ẩn là độ chính xác về số khi số lượng lớn; tuy nhiên, điều đó sẽ chỉ xảy ra nếu số lượng mảng được sử dụng vượt quá không gian địa chỉ của máy (số nguyên Perl đủ lớn để giữ con trỏ), điều không thể xảy ra trên một máy lý tưởng hóa.)
Cuối cùng, tất cả những gì chúng ta cần làm là đặt chương trình này vào một vài vòng lặp. Các for@F
vòng lặp, kết hợp với các -a
tùy chọn dòng lệnh, sẽ lặp trên các lĩnh vực đầu vào tiêu chuẩn (định nghĩa mặc định của "trường" ở đây sẽ chia vào khoảng trắng). Các redo
vòng lặp sẽ đặt toàn bộ chương trình trong một vòng lặp ngầm (trừ, thuận tiện, cách đọc của đầu vào tiêu chuẩn), mà sẽ làm cho chương trình để chạy trong một vòng lặp liên tục, theo yêu cầu của ngữ nghĩa của máy I / D.
eval
giải pháp giống như tầm thường .