Giải thích Kíp!


12

Giới thiệu

Kíp là một ngôn ngữ lập trình bí truyền dựa trên ngăn xếp được phát minh bởi Rune Berg vào tháng 3 năm 2003.

Kíp có 27 ngăn xếp, 4 toán tử và cấu trúc điều khiển.

Ngăn xếp

Các ngăn xếp được đặt tên a- zvà chứa các số nguyên có chữ ký 32 bit. Ngoài ra còn có một ngăn xếp đặc biệt @, để làm cho đầu ra số thuận tiện hơn. Khi một số được đẩy lên @, các giá trị ASCII của các chữ số đó thực tế được đẩy thay thế. (Ví dụ: nếu bạn đẩy 12 đến @, nó sẽ đẩy 49 và sau đó 50 để @thay thế.)

Đầu vào được đẩy lên ngăn xếp đầu vào itrước khi chương trình được thực thi. Trình thông dịch sẽ yêu cầu các giá trị để lưu trữ itrước khi thực hiện. Sau khi thực hiện kết thúc, mọi thứ trên ngăn xếp đầu ra osẽ được bật thành đầu ra dưới dạng ký tự ASCII. Vì đây là cơ chế IO duy nhất của Kíp, nên việc tương tác với chương trình Kíp là không thể.

Người vận hành

Một toán hạng là một định danh ngăn xếp hoặc một số nguyên 32 bit đã ký.

Đẩy: >hoặc<

Cú pháp: Operand>StackIndentifierhoặcStackIndentifier<Operand

Toán tử Push đưa toán hạng sang trái và đẩy nó vào ngăn xếp đã chỉ định. Ví dụ, 12>asẽ đẩy giá trị 12 lên ngăn xếp a. a>bsẽ bật giá trị trên cùng từ ngăn xếp avà đẩy nó lên ngăn xếp b. Popping một ngăn xếp trống luôn trả về 0. a<btương đương với b>a. a<b>cbật giá trị cao nhất từ bvà đẩy đến cả hai ca.

Thêm vào: +

Cú pháp: StackIndentifier+Operand

Toán tử Add đẩy tổng của mục trên cùng trên ngăn xếp và toán hạng lên ngăn xếp. Nếu toán hạng là một ngăn xếp, thì giá trị được bật ra từ nó. Ví dụ: nếu giá trị trên cùng của ngăn xếp alà 1, thì a+2sẽ đẩy 3 lên trên nó. Nếu atrống, sau đó a+2sẽ đẩy 2 lên nó. Nếu các giá trị trên cùng của ngăn xếp ablà 1 và 2, thì a+bsẽ bật giá trị 2 từ ngăn xếp bvà đẩy 3 lên ngăn xếp a.

Trừ đi: -

Cú pháp: StackIndentifier-Operand

Toán tử Subtract hoạt động chính xác như toán tử Add, ngoại trừ việc nó trừ thay vì thêm.

Thông thoáng: ?

Cú pháp: StackIndentifier?

Toán tử Clear làm trống ngăn xếp nếu mục trên cùng của nó là 0.

Trình thông dịch sẽ bỏ qua mọi thứ không nằm cạnh toán tử, vì vậy chương trình sau sẽ hoạt động : a+2 this will be ignored c<i. Tuy nhiên, cách thích hợp để thêm nhận xét là sử dụng #ký tự. Bất cứ điều gì giữa một #và một ký tự cuối dòng được loại bỏ trước khi thực hiện. Ký tự ASCII # 10 được định nghĩa là dòng cuối trong Kíp.

Toán tử có thể được chia sẻ bởi hai toán tử, ví dụ a>b c>b c?có thể được viết là a>b<c?.

Chương trình 1>a<2 a+asẽ dẫn đến việc achứa các giá trị [1 4](từ dưới lên trên) và không [1 3]. Tương tự như vậy cho các -nhà điều hành.

Cấu trúc điều khiển

Chỉ có một cấu trúc điều khiển trong Kíp: vòng lặp.

Cú pháp: (StackIndentifier code )

Miễn là ngăn xếp được chỉ định không trống, mã trong ngoặc đơn phù hợp sẽ được lặp lại. Vòng lặp có thể chứa các vòng lặp khác. Ví dụ, (a a>b)sẽ di chuyển tất cả các giá trị của ngăn xếp alên ngăn xếp b, mặc dù thứ tự sẽ bị đảo ngược . Một chức năng giống hệt nhau, nhưng thanh lịch hơn để làm điều này là (a>b).

Ví dụ

100>@ (@>o)

Điều này sẽ xuất 100

33>o 100>o 108>o 114>o 111>o 87>o 32>o 111>o 108>o 108>o 101>o 72>o

Điều này sẽ in "Hello World!". Khi ongăn xếp đang được xuất ra, nó bắt đầu bật các ký tự từ đầu ngăn xếp xuống dưới cùng.

#prime.k by Jannis Harder
u<200
#change 200


k<2>m
u-2
(u-1 u>t u>z u<t
  (k>e e+0 e>r)
  (e>k)
  m+1
  m>t
  m>z
  m<t
  t<0>z? t?
  1>g
  (r>b
    m+0 m>a
    b+0 b>w
    (a-1 
      b+0 b>j
      j?
      1>s
      (j<0>s j?)
      s?
      (s<0 w+0 w>b s?)
      a>t
      a>z
      t>a
      b-1
      b>t
      b>z
      t>b
      z<0>t? z?
    a?)
    b?
    1>p
    (b<0 b? 0>p)
    p?
    (p 0>r? 0>p? 0>g)
  )
  g?
  (g m+0 m>k 0>g?)
u?)
(k>@
  10>o
  (@>o)
)

Đây là một trình tạo số nguyên tố, nhưng tôi không chắc nó hoạt động như thế nào.

Quy tắc

  • Bạn phải viết một chương trình / chức năng diễn giải Kíp. Chương trình / chức năng này có thể nhận được chương trình Kíp thông qua tệp nguồn hoặc lấy trực tiếp qua STDIN từ người dùng. Nếu STDIN không có sẵn, nó phải lấy nó từ đầu vào bàn phím và tiếp tục nhận đầu vào cho đến khi nhập một ký tự không thể in cụ thể. Ví dụ: nếu trình thông dịch của bạn được viết bằng mã máy x86, nó sẽ lấy ký tự chương trình Kíp theo ký tự từ bàn phím và tiếp tục làm như vậy cho đến khi esc(hoặc bất kỳ phím nào khác không phát ra ký tự có thể in) được nhấn.

  • Nếu có lỗi, ví dụ như lỗi cú pháp hoặc lỗi tràn ngăn xếp, nó phải thừa nhận theo một cách nào đó, ví dụ bằng cách trả về 10 thay vì 0 hoặc thông báo lỗi do trình thông dịch / trình biên dịch tạo ra, NHƯNG KHÔNG IN THÔNG ĐIỆP LRI .

  • Bất kỳ quy tắc thông thường khác cho mã golf áp dụng cho thử thách này.

  • Mã của bạn sẽ được kiểm tra với một số ví dụ trong kho lưu trữ mẫu của Kíp

Đây là một . Mã ngắn nhất tính bằng byte sẽ giành chiến thắng. Chúc may mắn!


Lưu ý rằng có một toán tử tùy chọn trong Kíp, "nhưng nó không phải là một phần của đặc tả và chỉ là một tính năng bổ sung trong trình thông dịch chính thức. Tôi đã không đề cập đến nó ở đây vì vậy nó không cần phải được hỗ trợ trong trình của bạn.

Nếu bạn có bất kỳ nghi ngờ nào về bất kỳ phần nào của đặc tả, bạn có thể kiểm tra nó với trình thông dịch chính thức được viết bằng Java . Điều này sẽ tải xuống một tệp zip chứa chương trình biên dịch và mã nguồn. Nó được cấp phép theo GPL.


1
Chúng ta phải sử dụng số nguyên có chữ ký 32 bit hay chúng ta có thể đi với loại số nguyên tự nhiên của máy chủ không? (Các trường hợp quan trọng nhất có lẽ là số nguyên 32 bit không dấu, số nguyên 8 bit có dấu hoặc không dấu và số nguyên chính xác tùy ý.)
Martin Ender

tốt, đó là những gì tôi tìm thấy trên wiki bí truyền. có, bởi vì trình thông dịch của bạn có thể không tương thích với các chương trình núm vú khác mà cơ chế của họ dựa trên tính năng này

Bạn có thể cụ thể hơn về hành vi trong trường hợp lỗi? Vì vậy, chúng tôi có thể trả lại câu trả lời không chính xác hoặc phát ra lỗi, nhưng chúng tôi không thể in lỗi?
Alex A.

@Alex A. Có, bởi vì nó có thể được coi là đầu ra của chương trình và bạn có thể tạo một chương trình núm vú có thể có đầu ra giống như thông báo lỗi. Ngoài ra, "rẻ hơn" (sử dụng ít ký tự hơn) không có chức năng / câu lệnh in thông báo lỗi.

3
Khoảng trắng nào có thể xảy ra trong một chương trình nguồn? Làm thế nào tôi có thể yêu cầu đầu vào inếu tôi lấy chương trình nguồn từ stdin?
orlp

Câu trả lời:


6

C, 709 702 byte

Điểm byte là với các dòng mới (có thể được loại bỏ) bị xóa, nhưng để dễ đọc, tôi đăng nó ở đây với các dòng mới:

#define R return
#define C ;break;case
c[999]={};*P=c;*S[28];M[99999]={};t;*T;
u(s,v){S[s]+=28;*S[s]=v;
if(s>26){for(t=v/10;t;t/=10)S[s]+=28;T=S[s];do{*T=48+v%10;T-=28;}while(v/=10);}}
o(s){t=S[s]-M>27;S[s]-=28*t;R S[s][28]*t;}
I(s){R s<65?27:s-97;}
O(int*p){if(!isdigit(*p))R o(I(*p));
for(;isdigit(p[-1]);--p);for(t=0;isdigit(*p);t*=10,t+=*p++-48);R t;}

main(i,a){for(i=0;i<28;++i)S[i]=M+i;
for(;~(*++P=getchar()););P=c+1;
for(;;){i=I(P[-1]);switch(*P++){
case 35:for(;*P++!=10;)
C'<':u(i,O(P))
C'>':u(I(*P),O(P-2))
C'+':u(i,*S[i]+O(P))
C'-':u(i,*S[i]-O(P))
C'?':if(!*S[i])S[i]=M+i
C'(':for(i=1,T=P;i;++T)i+=(*T==40)-(*T==41);if(S[I(*P)]-M<28)P=T;else u(26,P-c)
C')':P=c+o(26)-1
C-1:for(;i=o(14);)putchar(i); R 0;}}}

Biên dịch với gcc -w golf.c ( -wcảnh báo im lặng cho sự tỉnh táo của bạn).

Hỗ trợ tất cả mọi thứ trừ iđầu vào, vì người hỏi chưa trả lời câu hỏi của tôi về cách thực hiện nếu bạn lấy mã từ stdin. Nó không báo cáo lỗi cú pháp.


Tôi đã trả lời câu hỏi của bạn về ngăn xếp "i" trong các bình luận của bài viết chính.

btw làm thế nào nó đọc chương trình núm vú? thông qua các đối số lệnh? Tôi nên sử dụng nó như thế nào?

@GLASSIC Nó mong đợi chương trình trên stdin.
orlp

Cho đến khi ? Làm thế nào để bắt đầu bài tiết?

@GLASSIC Chỉ cần vượt qua chương trình trên stdin. Ví dụ ./a.out < prime.k.
orlp

3

Ruby, 718 byte (hiện không lọc)

tôi vô cùng mệt mỏi

Tệp được tải dưới dạng đối số dòng lệnh và đầu vào được gửi qua STDIN. Ngoài ra, chuyển tệp vào STDIN nếu bạn không cần nhập vào isổ đăng ký.

Do một số nhầm lẫn liên quan đến thông số kỹ thuật, phiên bản hiện tại không được xử lý a<b>cđúng cách và do đó không thể xóa cho đến khi được sửa.

a<b>cđược sửa chữa ngay bây giờ. Tuy nhiên, nó vẫn trả về kết quả sai khi chạy hàm số nguyên tố, vì vậy nó vẫn là một câu trả lời không thể lọc được.

(f=$<.read.gsub(/#.*?\n|\s[^+-<>#()?]*\s/m,' ').tr ?@,?`
t=Array.new(27){[]}
t[9]=STDIN.read.bytes
k=s=2**32-1
r=->c{c=c[0];c[0]==?(?(s[c[1..-2]]while[]!=t[c[1].ord-96]):(c=c.sub(/^(.)<(\D)>(.)/){$1+"<#{t[$2.ord-96].pop||0}>"+$3}.sub(/(\d+|.)(\W)(\d+|.)?/){_,x,y,z=*$~
a=x.ord-96
b=(z||?|).ord-96
q=->i,j=z{j[/\d/]?j.to_i: (t[i]||[]).pop||0}
l=t[a]
y<?-?(x==z ?l[-1]*=2:l<<(l.pop||0)+q[b]
l[-1]-=k while l[-1]>k/2):y<?.?(x==z ?l[-1]=0:l<<(l.pop||0)-q[b]
l[-1]+=k while l[-1]<-k/2-1):y<?>?t[a]+=a<1?q[b].to_s.bytes: [q[b]]:y<???
(t[b]+=b<1?q[a,x].to_s.bytes: [q[a,x]]): l[-1]==0?t[a]=[]:0
z||x}while c !~/^(\d+|.)$/)}
s=->c{(z=c.scan(/(\((\g<1>|\s)+\)|[^()\s]+)/m)).map &r}
s[f]
$><<t[15].reverse.map(&:chr)*'')rescue 0

+1 dù sao đi nữa. Bạn đã thử chương trình Dailymotion chưa?
edc65

@ edc65 Chương trình trình tự Fftimeacci cũng in sai: 0 1 1 2 4 8 16...Tôi tự hỏi liệu đó có phải là lỗi thông số không
Giá trị Ink

Không, chương trình Fibonacci là tào lao, ví dụ như dòng a+0này là vô nghĩa
edc65

Tôi đoán vấn đề về số nguyên tố là nó không xử lý các cấu trúc điều khiển lồng nhau, nhưng tôi không biết nhiều về ruby, tôi nghi ngờ chính xác của tôi là đúng.

Chương trình này sẽ xử lý các bộ parens lồng nhau đúng cách vì khớp regex đệ quy trên /(\((\g<1>|\s)+\)|[^()\s]+)/mđó sử dụng để phân tách trên các mã thông báo và các nhóm mã thông báo. ( Kiểm tra nó trên regex101 ). Đây có thể là một lỗi trong phần còn lại của phân tích cú pháp của tôi, nhưng tôi không biết ở đâu.
Mực giá trị
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.