Haskell , 3 quines, 1119 byte
Câu 1, 51 byte
Một IO
hành động ẩn danh in trực tiếp đến thiết bị xuất chuẩn.
putStr`mappend`print`id`"putStr`mappend`print`id`"
Hãy thử trực tuyến!
Quine 2, 265 byte
Hàm f
lấy một đối số giả và trả về một chuỗi.
f c=[b=<<g]!!0++show g;b c=[[[show 9!!0,show 1!!0..]!!6..]!!c];g=[93,0,90,52,82,89,52,51,51,94,84,24,24,39,34,34,106,95,102,110,0,94,50,89,0,90,52,82,82,82,106,95,102,110,0,48,24,24,39,35,106,95,102,110,0,40,24,24,39,37,37,84,24,24,45,37,37,84,24,24,90,84,50,94,52]
Hãy thử trực tuyến!
Quine 3, 803 byte
Tất cả mọi thứ sau LANGUAGE
pragma là một hàm bất thường lấy một đối số giả và trả về một chuỗi.
{-#LANGUAGE CPP#-}(\q(_:_:_:_:_:_:_:_:z)y(#)_->(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z)'\''__TIME__(\(?)v k x->v$k?x)$ \(&)(%)v->v&'{'&'-'&'#'&'L'&'A'&'N'&'G'&'U'&'A'&'G'&'E'&' '&'C'&'P'&'P'&'#'&'-'&'}'&'('%'\\'&'q'&'('&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'z'&')'&'y'&'('&'#'&')'&'_'&'-'&'>'&'('&'y'&'('%'\\'&'k'&' '&'x'&'-'&'>'%'\''&'&'%'\''&':'&'q'&':'&'k'&':'&'q'&':'&'x'&')'&'#'&'y'&'('%'\\'&'k'&' '&'x'&'-'&'>'%'\''&'%'%'\''&':'&'q'&':'%'\''%'\\'%'\\'%'\''&':'&'k'&':'&'q'&':'&'x'&')'&'$'&'y'&'('&':'&')'&'#'&'y'&'('&':'&')'&'$'&' '%'\\'&'x'&'-'&'>'&'x'&')'&'z'&')'%'\''%'\\'%'\''%'\''&'_'&'_'&'T'&'I'&'M'&'E'&'_'&'_'&'('%'\\'&'('&'?'&')'&'v'&' '&'k'&' '&'x'&'-'&'>'&'v'&'$'&'k'&'?'&'x'&')'&'$'&' '%'\\'&'('&'&'&')'&'('&'%'&')'&'v'&'-'&'>'&'v'
Hãy thử trực tuyến!
Nhân vật
Câu 1:
"S`adeimnprtu
Câu 2:
!+,.0123456789;<=[]bcfghosw
Câu 3:
#$%&'()-:>?ACEGILMNPTU\_kqvxyz{}
Làm thế nào nó hoạt động
Câu 1
putStr`mappend`print`id`"putStr`mappend`print`id`"
Quine 1 là phiên bản sửa đổi của Golf gần đây của tôi , bạn trả lời câu hỏi (với những cải tiến của H.PWiz):
- Vì các chương trình đầy đủ là không cần thiết,
main=
đã được gỡ bỏ.
<>
và $
đã được thay thế bởi các từ đồng nghĩa gần mappend
và id
.
Điều này giải phóng các nhân vật quan trọng =<>
và toán tử hữu ích $
cho các nhiệm vụ khác.
Câu 2
f c=[b=<<g]!!0++show g;b c=[[[show 9!!0,show 1!!0..]!!6..]!!c];g=[93,0,......]
Quine 2 sử dụng các phương thức hơi giống với chương trình 2 trong câu trả lời Quines độc quyền gần đây của tôi , nhưng được điều chỉnh theo cách trực tiếp và đặc biệt là để tránh sử dụng các ký tự, cần thiết cho quine 3. Cả hai đều đạt được với sự trợ giúp của show
hàm, mà may mắn là chưa có nhân vật nào được sử dụng.
Câu hỏi này sử dụng các tab thay vì khoảng trắng, nhưng tôi đã sử dụng khoảng trắng bên dưới để dễ đọc.
g
là dữ liệu quine, như một danh sách các số nguyên ở cuối mã. Mỗi số đại diện cho một ký tự từ phần còn lại của mã.
- Các số được dịch chuyển theo
9
, vì vậy đó là tab 0
. Điều này làm cho mã hóa ngắn hơn một chút bằng cách cho phép các chữ cái viết thường cho hàm và tên biến phù hợp với 2 chữ số.
b c=[[[show 9!!0,show 1!!0..]!!6..]!!c]
là một hàm để chuyển đổi một số thành một ký tự (thực ra là một chuỗi một ký tự).
[[show 9!!0,show 1!!0..]!!6..]
là một phạm vi ký tự bắt đầu bằng một ký tự tab, được lập chỉ mục với !!c
.
- Các ký tự tab riêng của mình được sản xuất bởi lập chỉ mục vào phạm vi khác
[show 9!!0,show 1!!0..]
, bắt đầu với ký tự chữ số '9'
và '1'
và nhảy xuống trong bước 8.
- Các ký tự chữ số được tạo ra bằng cách lập chỉ mục vào
show
chuỗi của chữ số tương ứng.
f c=[b=<<g]!!0++show g
là chức năng chính. c
là một đối số giả.
b=<<g
sử dụng =<<
để chuyển đổi từng số g
thành ký tự của nó. (Việc sử dụng =<<
chứ không phải là ví dụ map
là tại sao b
cần phải bọc ký tự trả về của nó trong danh sách.)
show g
đưa ra biểu diễn chuỗi của g
danh sách và ++
nối các chuỗi.
- Bởi vì
=<<
có quyền ưu tiên thấp hơn ++
, một số dấu ngoặc là cần thiết. Để tránh sử dụng ()
(dành riêng cho quine 3), hãy [...]!!0
lập chỉ mục vào một danh sách với một thành phần.
Câu 3
Theo thiết kế của các quine khác, quine 3 vẫn có quyền truy cập vào dấu ngoặc đơn, biểu thức lambda, ký tự ký tự và hàm tạo chuỗi / danh sách :
. Đây sẽ là đủ để xây dựng một hàm prepends mã của Quine thành một chuỗi.
Thật không may, tất cả các nguyên âm chữ thường (trừ đôi khi y
) đã được sử dụng, không để lại các hàm dựng sẵn chữ và số hữu ích. Cũng []""
đã biến mất. Điều này không có cách bình thường để xây dựng một chuỗi trống để bắt đầu giả vờ mã.
Tuy nhiên, gần như tất cả các chữ cái viết hoa vẫn có sẵn, do đó, một LANGUAGE
pragma để có được một phần mở rộng ngôn ngữ là có thể. Một lần nữa bởi may mắn, CPP
(kích hoạt bộ tiền xử lý C) là phần mở rộng ngôn ngữ duy nhất được đặt tên chỉ bằng chữ in hoa. Và các macro CPP thường có tên viết hoa.
Vì vậy, để có được chuỗi rỗng thiết yếu, quine cho phép CPP
, sử dụng __TIME__
macro để lấy hằng số chuỗi có dạng "??:??:??"
(được đảm bảo thuận tiện để luôn có cùng độ dài) và mẫu khớp với nó.
{-#LANGUAGE CPP#-}(\q(_:_:_:_:_:_:_:_:z)y(#)_->(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z)'\''__TIME__(\(?)v k x->v$k?x)$ \(&)(%)v->v&'{'&'-'&......
Sau pragma ngôn ngữ, quine bao gồm một biểu thức lambda ràng buộc các tham số của nó với bốn đối số này (để lại một tham số giả cuối cùng _
sẽ được áp dụng sau):
q
ràng buộc '\''
, đưa ra một nhân vật trích dẫn duy nhất;
_:_:_:_:_:_:_:_:z
bị ràng buộc __TIME__
, hay còn gọi là một chuỗi như "??:??:??"
vậy, do đó tạo ra z
một chuỗi rỗng;
y
bị ràng buộc với (\(?)v k x->v$k?x)
, một bộ kết hợp lambda được sử dụng để giúp chuyển đổi dữ liệu quine từ dạng liên kết trái ("Foldl") sang dạng liên kết phải ("Foldr");
- Toán tử
(#)
ràng buộc với\(&)(%)v->v&'{'&'-'&...
, dữ liệu quine chính nó.
Dữ liệu quine được đưa ra dưới dạng mã hóa Church, biểu thức lambda với các tham số (&)(%)v
.
- Bằng cách áp dụng biểu thức cho các giá trị cụ thể để khởi tạo
(&)
,(%)
và v
, mã hóa này có thể được sử dụng một trong hai để xây dựng mã cốt lõi của Quine hoặc để xây dựng lại biểu diễn dữ liệu Quine riêng của mình.
- Theo quy tắc sửa lỗi mặc định của Haskell
&
và%
trở thành các nhà khai thác liên kết bên trong lambda. Do đó, các tham số ký tự được kết hợp với v
bắt đầu từ bên trái.
- Đối với hầu hết các nhân vật
k
, có một tương ứng&'k'
.
- Khi
k
là '
hay \
, mà cần phải được thoát bên literals nhân vật, mã hóa là thay %'\k'
.
Vì mã hóa dữ liệu là liên kết trái, nhưng các chuỗi được xây dựng theo cách kết hợp phải, nên bộ kết hợp y = (\(?)v k x->v$k?x)
được giới thiệu để làm cầu nối không khớp.
y(...)
được dự định để xây dựng các chức năng phù hợp để sử dụng như các toán tử (&)
và (%)
toán tử quine .
v
là một hàm từ chuỗi đến chuỗi ( v
ví dụ dự định của dữ liệu quine ).
k
là một ký tự, x
một chuỗi và ?
một toán tử kết hợp chúng thành một chuỗi mới. (Đối với mã lõi,(?)=(:)
. Để thực sự tái cấu trúc biểu diễn dữ liệu quine, nó phức tạp hơn.)
- Vì vậy,
y(?)v k = \x->v$k?x
là một chức năng khác từ chuỗi đến chuỗi.
Như một ví dụ về cách điều này thay đổi tính kết hợp, nếu (&)=y(:)
:
(v&k1&k2&k3) x
= (((v&k1)&k2)&k3) x
= y(:)(y(:)(y(:)v k1)k2)k3 x
= y(:)(y(:)v k1)k2 (k3:x)
= y(:)v k1 (k2:(k3:x))
= v (k1:(k2:(k3:x)))
= v (k1:k2:k3:x)
Tổng quát hơn, khi nào (#)
là hàm dữ liệu quine và f1,f2
là các hàm kết hợp các ký tự với chuỗi:
(y(f1)#y(f2)$v) x
= (...(y(f1)(y(f1)v '{') '-')...) x
= v(f1 '{' (f1 '-' (... x)))
áp dụng hàm dữ liệu quine với (&)=y(f1)
và (%)=y(f2)
, và điều này sử dụng quy định f1
và f2
để kết hợp các ký tự của dữ liệu quine với x
, và sau đó chuyển chuỗi kết quả tớiv
.
Phần thân của biểu thức lambda chính đặt tất cả lại với nhau:
(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z
'&':q:k:q:x
cho một nhân vật k
prepends &'k'
vào chuỗi x
, trong khi '%':q:'\\':k:q:x
prepends %'\k'
, đó là hình thức dữ liệu Quine ban đầu của họ.
- Do đó,
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x
là các tham số phù hợp để xây dựng lại biểu diễn dữ liệu quine, được thêm vào cuối cùng z
(chuỗi trống), và sau đó được chuyển sang hàm sau.
y(:)#y(:)
là các tham số phù hợp để thêm mã lõi của quine vào chuỗi, mà không cần sửa đổi khác.
- Cuối cùng, không
\x->x
được làm gì với quine được xây dựng, được trả lại.