Chào thế giới! (Mọi nhân vật khác)


129

Viết chương trình in "Xin chào, Thế giới!". Nhưng ngoài ra, nếu bạn chỉ lấy các ký tự đầu tiên, thứ ba, thứ năm, v.v. của chương trình, thì chương trình kết quả vẫn sẽ in "Xin chào, Thế giới!".

Nếu chương trình của bạn là:

abc
def

Nó sẽ xuất ra "Xin chào, Thế giới!", Nhưng vì vậy nên

acdf

Không có giải pháp nào có ít hơn 2 ký tự.


2
Có thể có khoảng trắng xung quanh đầu ra?
vroomfondel

18
Bài đăng đầu tiên tuyệt vời!
Adám

11
Nhìn thấy tất cả các câu trả lời với "HHeelllloo" làm tôi nhớ đến việc nói Cá voi.
Brian Minton

32
Mẹo chuyên nghiệp để tránh "Xin chào, Thế giới!" tích hợp sẵn trong các thử thách như thế này: sử dụng một chuỗi hơi phức tạp tương tự khác nhau như "Lời chào, Trái đất!"
Martin Ender

6
"Không có giải pháp nào có ít hơn 2 ký tự." Kinh ngạc.
Robert Grant

Câu trả lời:


195

Python 3 , 61 byte

rant="partisn't"
print(("HHeelllloo,,  WWoorrlldd!!"""[::2]))

Hãy thử trực tuyến!

Lạm dụng thực tế đó printlà một chức năng trong Python 3 :)

Giải pháp tối thiểu đảng bạn sẽ tìm thấy ở đây trên PPCG.

Trở thành

rn=print
rn("Hello, World!"[:])

48
Thật là đẹp
sĩ523

1
@ musicman523 Nhưng, Không REPL bao quanh văn bản với dấu ngoặc đơn trong trường hợp đó.
chính thức tuyên bố

1
@officialaimm Vâng, tôi cho là có
sĩ523

1
@ yamboy1 Thử xóa mọi chữ cái khác
vroomfondel

1
Tôi không biết [:]thực sự đã làm việc: o Nice!
HyperNeutrino

56

Hồng y , 29 byte

%
"
H
e
l
l
o
,
 
W
o
r
l
d
!

Hãy thử trực tuyến!

Xóa mọi ký tự khác sẽ xóa tất cả các nguồn cấp dữ liệu, điều này vẫn dẫn đến Hello, World!:

%"Hello, World!

Hãy thử trực tuyến!

Lý do công việc này là %tạo ra bốn con trỏ chỉ dẫn, di chuyển theo từng hướng trong bốn hướng chính. IP để lại mã nguồn được loại bỏ đơn giản. Vì vậy, trong trường hợp đầu tiên, chỉ còn IP phía nam còn lại và trong trường hợp thứ hai, chỉ còn lại IP phía đông, tất cả những cái khác chỉ đơn giản là bị bỏ. Trong cả hai trường hợp, chương trình thực hiện sau đó chỉ là "Hello, World!. Chuyển "sang chế độ chuỗi trong đó mỗi ô được in đơn giản thành STDOUT. Chúng ta không cần chấm dứt chuỗi, vì để lại mã nguồn vẫn chấm dứt chương trình.

Lưu ý rằng cùng một ý tưởng hoạt động trong Beeswax , sử dụng *thay vì %`thay vì "(điều này là do Beeswax chủ yếu lấy cảm hứng từ Cardinal nhưng sử dụng lưới lục giác).

Hãy thử trực tuyến! (dọc) | | Hãy thử trực tuyến! (ngang)



31

Trên thực tế , 2 byte

HH

Giải trình:

H, như bạn có thể mong đợi, đẩy Hello, World!vào ngăn xếp.

Chương trình chính ( HH) sẽ gặp lần đầu tiên Hvà đẩy Hello, World!lên ngăn xếp. HTuy nhiên, ở lần thứ hai , nó sẽ cố gắng sử dụng hai đối số (vì ngăn xếp cần trống để đẩy Hello, World!) và thất bại. Tuy nhiên, lỗi này sẽ bị bỏ qua và sau đó Hello, World!sẽ được in ngầm.

Chương trình thứ hai ( H) sẽ đẩy Hello, World!một lần và nó sẽ được in ra.

Điều này tương tự như câu trả lời 2 byte của Fatalize, nhưng điều này không thực sự "gian lận".

Hãy thử trực tuyến!


4
Giải pháp hay, nhưng tôi nghĩ điều này không nên tính vì nó quá giống giải pháp một nhân vật.
Leo Tenenbaum

32
@LeoTenenbaum Tại sao không? Nó phù hợp với các quy tắc hoàn toàn tốt.
Okx

2
Những gì bạn giải thích không phải là trường hợp, Hsẽ chỉ đẩy Hello, World!vào một ngăn xếp trống và nếu ngăn xếp không trống, nó sẽ mong đợi 2 đối số, do đó sẽ có một lỗi và các lỗi sẽ bị bỏ qua. Và không thực sự không chỉ in phần tử trên cùng.
Erik the Outgolfer

@EriktheOutgolfer Rất tiếc. Sẽ sửa chữa.
Okx

Đây là lý do tại sao thực sự là ngôn ngữ chơi golf yêu thích của tôi. Đó là ở mức độ hoàn hảo của ngu ngốc.
RShields

22

Lua , 89 byte

--- [ [
print("Hello, World!")
--[[ ] ]
pCrAiLnCtU(L"AHTeOlRlFoE,L IWNoEr:lDd !:"D)
---]]

Hãy thử trực tuyến! Như cú pháp tô sáng cho thấy, đây là lạm dụng bình luận lớn.

Luân phiên:

--[[pit"el,Wrd"
-[]]print("Hello, World!")--]

Hãy thử trực tuyến!

Và để thuận tiện, một chương trình để chuyển đổi một chương trình thành mọi dạng nhân vật khác: Hãy thử trực tuyến!


Tôi thích cái này! Định dạng nhận xét của Lua có vẻ tương tự như T-SQL, tôi sẽ thử và làm việc với một ngôn ngữ đó.
BradC

3
Loại mẹo này sẽ hoạt động với mọi ngôn ngữ có cả nhận xét khối và nhận xét dòng (C, JS, v.v.)
CalculatorFeline

2
TÍNH TOÁN: D: D
Đạp xe

2
HHeelllloo WWoorrlldd!!thật nhàm chán: P
CalculatorFeline

19

Võng mạc , 39 byte


HHeelllloo,,  WWoorrlldd!!


(.).x?
$1

Hãy thử trực tuyến!

Lấy mọi nhân vật khác cho:


Hello, World!
()x
1

Hãy thử trực tuyến!

Chương trình đầu tiên tạo ra một chuỗi với lời chào được nhân đôi. Sau đó, nó thay thế từng cặp nhân vật bằng ký tự đầu tiên. Ngoài ra còn có một giai đoạn trống thay thế tất cả các chuỗi trống bằng các chuỗi trống ở giữa, nhưng điều đó không làm gì cả. Chương trình thứ hai không khớp với chữ "x" vì vậy nó không thay thế bất cứ điều gì sau khi tạo lời chào.

Có lẽ thú vị hơn, nếu giai đoạn thứ ba được thay đổi một chút, tập hợp các ký tự đầu tiên không phải là cùng một thông điệp. Điều này có thể dẫn đến nhiều giải pháp chiều dài giống hệt nhau như đầy đủgiảm một nửa .



17

Haskell , 85 byte

{--}main=putStr"Hello, World!"--} m a i n = p u t S t r " H e l l o ,   W o r l d ! "

Hãy thử trực tuyến!

Mỗi ký tự thứ hai bị xóa:

{-mi=uSrHlo ol!-}main=putStr"Hello, World!"

Hãy thử trực tuyến!

Điều này khai thác hai định dạng bình luận trong Haskell: {- -}cho các bình luận nội tuyến hoặc nhiều dòng và --để bình luận phần còn lại của dòng.


16

Javascript, 67 byte

/**/alert`Hello, World`// * / a l e r t ` H e l l o ,   W o r l d `

Mỗi thư thứ hai bị xóa:

/*aetHlo ol`/*/alert`Hello, World`

Giống như câu trả lời Haskell của Laikoni, điều này khai thác ý kiến.


Câu trả lời hay, +1! Đã lưu 2 byte bằng cách tạo một cổng câu trả lời của bạn trong câu trả lời Java 8 của tôi và một byte bổ sung khi tôi đổi // * /thành //**/(điều không may là không thể trong trường hợp của bạn do /**/alert`Hello, World` là một lượng byte lẻ, thay vì thậm chí như trong trường hợp của tôi .
Kevin Cruijssen

14

Brachylog , 4 byte

Ḥ~wḤ

Hãy thử trực tuyến!

Giải trình

~wghi biến phải của nó vào STDOUTvà bỏ qua đối số bên trái của nó. "Hello, World!", vì vậy bản in này Hello, World!.

Nếu chúng ta chỉ lấy ký tự thứ nhất và thứ ba, chúng ta sẽ nhận được Ḥw. Trong trường hợp đó, wviết biến trái của nó và bỏ qua biến phải của nó, vì vậy nó cũng in Hello, World!.

2 byte

ḤḤ

Hãy thử trực tuyến!

Về mặt kỹ thuật, đây là một câu trả lời hợp lệ, nhưng điều này thống nhất biến đầu ra của chương trình thay vì in ra STDOUT, vì vậy tôi đoán chương trình 4 byte mang nhiều tinh thần của thách thức.


Tôi không nghĩ câu trả lời 2 byte là 'về mặt kỹ thuật' là hợp lệ, vì các trạng thái thách thức được in .
Okx

1
@Okx in, như trên một tờ giấy?
theonlygusti

@theonlygusti Có nghĩa là in ra STDOUT.
Okx

5
@theonlygusti Thở dài ... đó là những gì có nghĩa là in theo mặc định.
Okx

3
@Okx bạn đang cố gắng trở thành người phạm tội để vô hiệu hóa một giải pháp, nhưng thực sự không có gì không hợp lệ về nó. Thách thức chỉ nói "đầu ra."
theonlygusti

11

Haskell, 102 byte

Chương trình đầy đủ:

main= putStr"Hello, World!";;
putSt   x ="p u t S t r  \" H e l l o ,   W o r l d !\"";
mmaaiin = main

và với mọi ký tự khác bị xóa:

mi=ptt"el,Wrd";ptt x=putStr "Hello, World!";main=mi

Bạn có thể tắt 2 byte bằng cách xóa khoảng trắng giữa p u t S t r\".
Sriotchilism O'Z cổ

11

mã máy x86, 162 byte

bản giới thiệu

PROG.COM Tải xuống và chạy nó trong trình giả lập MS-DOS , ví dụ như DOSBox .

90 B3 B4 B4 02 90 90 B3 B2 B2 48 90 90 B3 CD CD 21 90 90 B3 B2 B2 65 90 
90 B3 CD CD 21 90 90 B3 B2 B2 6C 90 90 B3 CD CD 21 90 90 B3 CD CD 21 90 
90 B3 B2 B2 6F 90 90 B3 CD CD 21 90 90 B3 B2 B2 2C 90 90 B3 CD CD 21 90 
90 B3 B2 B2 20 90 90 B3 CD CD 21 90 90 B3 B2 B2 77 90 90 B3 CD CD 21 90 
90 B3 B2 B2 6F 90 90 B3 CD CD 21 90 90 B3 B2 B2 72 90 90 B3 CD CD 21 90 
90 B3 B2 B2 6C 90 90 B3 CD CD 21 90 90 B3 B2 B2 64 90 90 B3 CD CD 21 90 
90 B3 B2 B2 21 90 90 B3 CD CD 21 90 90 B3 CD CD 20 90

Sau khi gỡ bỏ Tải xuống MINI.COM

90 B4 02 90 B2 48 90 CD 21 90 B2 65 90 CD 21 90 B2 6C 90 CD 21 90 CD 21 
90 B2 6F 90 CD 21 90 B2 2C 90 CD 21 90 B2 20 90 CD 21 90 B2 77 90 CD 21 
90 B2 6F 90 CD 21 90 B2 72 90 CD 21 90 B2 6C 90 CD 21 90 B2 64 90 CD 21 
90 B2 21 90 CD 21 90 CD 20

Làm thế nào để chạy?

Cài đặt DOSBox, cho Ubuntu / Debian

sudo apt install dosbox

Chạy nó

dosbox

Trong DOSBOX

mount c /home/user/path/to/your/directory
c:
PROG.COM
MINI.COM

Nó làm việc như thế nào?

Mã hoạt động của máy đại diện cho hướng dẫn ngôn ngữ lắp ráp .

Trong MS-DOS để in char, bạn sẽ thiết lập các thanh ghi và thực hiện ngắt. Thanh ghi AH sẽ là 0x02, thanh ghi DL chứa char của bạn. Vectơ ngắt là 0x21.

mov ah,0x2  ;AH register to 0x2 (B4 02)
mov dl,0x48 ;DL register to "H" (B2 48)
int 0x21    ;0x21 interrupt     (CD 21)

Mô hình tập tin COM của MS-DOS rất tốt, vì nó không có bất kỳ tiêu đề nào . Nó bị giới hạn bởi 64K, nhưng trong trường hợp của chúng tôi thì không vấn đề gì.

Để dừng chương trình, sử dụng ngắt 0x20

int 0x20    ;0x20 interrupt     (CD 20)

ma thuật

Nếu bạn muốn thực thi lệnh opcode 0xAB với một tham số 0xCD , bạn viết

AB CD

Trong PROG.COM

90 B3 AB AB CD 90
nop         ; No operation (90)
mov bl,0xb4 ; BL register to AB (B3 AB)
AB CD command (AB CD)
nop         ; No operation (90)

Trong MINI.COM

90 AB CD
nop         ; No operation (90)
AB CD command (AB CD)

Đó là mã máy bằng nhau , nếu bạn không sử dụng thanh ghi BL .

Máy phát điện

Chuyển đổi tập tin văn bản với hex thành hex nhị phân

cat hex_file | xxd -r -p > exec.com


Xóa tất cả `90 90` cho -52 byte.
NieDzejkob

Ngoài ra, cuối cùng sẽ không bao giờ đạt được.
NieDzejkob

10

Bình thường , 31 byte

p% 2"HHeelllloo,,  WWoorrlldd!!

Hãy thử trực tuyến!

Trở thành

p "Hello, World!

Cảm ơn @CalculatorFeline đã chỉ ra lỗi và xóa một byte.


Nhân vật giữ bắt đầu từ cái đầu tiên, không phải cái thứ hai. Bạn có thể thả không gian hàng đầu.
Máy

À, cảm ơn @CalculatorFeline. Tôi đọc "Take" là "Remove" trong thông số kỹ thuật.
vroomfondel


7

05AB1E , 29 byte

”™ ,ï‚‚ï ! ”# ¦2 ä ø¨øJð ý

Hãy thử trực tuyến!

Giải trình

”™ ,ï‚‚ï ! ”                # push the string "Weekly Hello , Changed World ! "
               #               # split on spaces
                               # RESULT: ['Weekly','Hello',',','Changed','World','!','']
                ¦              # remove the first element (Weekly)
                 2ä            # split in 2 parts
                               # RESULT: [['Hello', ',', 'Changed'], ['World', '!', '']]
                   ø           # zip
                               # RESULT: [['Hello', 'World'], [',', '!'], ['Changed', '']]
                    ¨          # remove the last element
                     ø         # zip
                               # RESULT: [['Hello', ','], ['World', '!']]
                      J        # join each inner list
                       ðý      # join on space

Sau khi loại bỏ mọi ký tự khác, chúng ta chỉ còn lại mã

”Ÿ™,‚ï!” 2äøøðý

Hãy thử trực tuyến!

Giải trình

”Ÿ™,‚ï!”       # push the string "Hello, World!"
        2ä     # split in 2 parts
               # RESULT: ['Hello, ', 'World!']
          ø    # zip, as the string has an odd length the space is lost
               # RESULT: ['HW', 'eo', 'lr', 'll', 'od', ',!']
           ø   # zip again
               # RESULT: ['Hello,', 'World!']
            ðý # join on space

7

Toán học, 62 byte

P0r0i0n0t0@0"0H0e0l0l0o0,0 0W0o0r0l0d0!0"Print@"Hello, World!"

Nó trả về "0H0e0l0l0o0,0 0W0o0r0l0d0!0" Null P0r0i0n0t0[0], và in Hello, World!như một hiệu ứng phụ. Khi chạy dưới dạng chương trình (không phải trong REPL), giá trị trả về sẽ không được in.

Sau khi loại bỏ mọi ký tự khác:

Print@"Hello, World!"rn@Hlo ol!

Nó trả lại Null ol! rn[Hlo], và in Hello, World!.


7

Thạch , 26 25 byte

““3ḅaė;œ»ḷ“ 3 ḅ a ė ; œ »

Hãy thử trực tuyến!

Sau khi xóa từng ký tự thứ hai, chúng ta sẽ để lại đoạn mã sau.

“3a;»“3ḅaė;œ»

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

““3ḅaė;œ»ḷ“ 3 ḅ a ė ; œ »  Main link.

““3ḅaė;œ»                  Index into Jelly's dictionary to yield
                           ["", "Hello, World!"]. 
          “ 3 ḅ a ė ; œ »  Index into Jelly's dictionary to yield.
                          " FullERebitingBEfluffiest adoptable".
         ḷ                 Take the left result.
“3a;»“3ḅaė;œ»  Main link.

“3a;»          Index into Jelly's dicrionary to yield " N-".
               Set the argument and the return value to the result.
     “3ḅaė;œ»  Index into Jelly's dicrionary to yield "Hello, World!".
               Set the return value to the result.

7

Về cơ bản v2.1 , 222 byte

+0503 @@6 :22 //1 +050501 @@6 :55 +0502 @@6@6 :33 //1 +050502 @@6 :55 +03 //1 +04 @@6 :55 //1 +03 @@6 :55 +01 //1 +0504 @@6 :33 //1 +050502 @@6 :55 +01 //1 +050502 @@6 :55 +0502 @@6 :11 //1 +050501 @@6 :55 +01 //1 +03 @@6

Hãy thử trực tuyến!

Mỗi chữ cái khác:

+53@6:2/1+551@6:5+52@66:3/1+552@6:5+3/1+4@6:5/1+3@6:5+1/1+54@6:3/1+552@6:5+1/1+552@6:5+52@6:1/1+551@6:5+1/1+3@6

Hãy thử trực tuyến!



6

Giúp tôi với, WarDoq! , 2 byte

Hi

Hãy thử trực tuyến!

Hin Hello, World!, ilà một không-op.

Giúp tôi với, WarDoq! có thể thêm hai số và kiểm tra các số nguyên tố, vì vậy nó được coi là ngôn ngữ lập trình hợp lệ cho mỗi bài đăng meta này .


Tại sao điều này bị hạ thấp?
Uriel

NOP và không gian rộng lớn chống lại tinh thần.
RShields

1
+1 vì tính mới về cách mã nguồn kết quả nhấn mạnh lại thông điệp nhận được đầu ra.
TUYỆT VỜI 04/07/2017


6

PHP, 53 byte

#
echo date(
$e_c_h_o='\H\e\l\l\o\,\ \W\o\r\l\d\!
');

Với mọi ký tự khác bị xóa:

#eh ae
echo'Hello, World!';

6

Octave, 49 45 byte

Đã lưu 4 byte vì Octave không yêu cầu dấu ngoặc để thực hiện lập chỉ mục.

'HHeelllloo,,  WWoorrlldd!! ' (1:2 : 3 ^ 3)''

Hãy thử trực tuyến!

Và một trong những giảm:

'Hello, World!'(:    )'

Hãy thử trực tuyến!

Giải trình:

Mã ban đầu có các chữ cái trong chuỗi được nhân đôi, do đó chúng tôi sẽ bỏ đi Hello, World!khi mỗi giây bị xóa. Một số khoảng trắng được thêm vào để đảm bảo dấu ngoặc và dấu nháy đơn được giữ.

Việc lập chỉ mục là thực sự 1:2:end. Có 27 ký tự và chúng tôi không thể sử dụng endhoặc 27vì chúng tôi phải xóa một ký tự, vì vậy chúng tôi sẽ 3 ^ 3thay thế. Khi chúng tôi xóa tất cả các nhân vật thứ ba, việc lập chỉ mục trở nên (:)(và một số không gian bổ sung).

(:)có nghĩa là "làm phẳng và biến thành một vectơ dọc" . Vì vậy, chúng ta cần hoán chuyển nó, sử dụng '. Chúng ta không cần hoán đổi chuỗi trong mã gốc, nhưng chuyển đổi gấp đôi hoạt động, do đó, chuỗi đầu tiên được hoán chuyển hai lần bằng cách sử dụng ''và chuỗi thứ hai được hoán chuyển chỉ một lần.


6

APL (Dyalog) , 35 34 byte

-1 cảm ơn Martin Ender.

'0H0e0l0l0o0,0 0W0o0r0l0d0!0'~  0

Hãy thử trực tuyến!

'0H0e0l0l0o0,0 0W0o0r0l0d0!0' tin nhắn với số không là ký tự phụ có thể tháo rời

~ ngoại trừ

 được định dạng (xâu chuỗi)

0 số không

Để lại chỉ các nhân vật kỳ lạ, điều này trở thành 'Hello, World!' .



5

Javascript, 73 byte

a ='a0l0e0r0t0`0H0e0l0l0o0,0 0W0o0r0l0d0!0`0/0/';eval(a.replace(/0/g,''))

Xây dựng một chuỗi avới nội dung a0l0e0r0t0`0H0e0l0l0o0,0 0W0o0r0l0d0!0`0/0/, sau đó loại bỏ tất cả những gì 0cần cung cấp alert`Hello, World!`//, đó là eval'd.

Lấy mọi nhân vật khác của chương trình mang lại

a=alert`Hello, World!`//;vlarpae//,')

thông báo Hello, Worldbằng cách sử dụng cú pháp chuỗi mẫu giống như những gì đã được đánh giá trong chương trình đầy đủ, sau đó lưu kết quả của cuộc gọi avà bao gồm nhận xét sâu sắc //;vlarpae//,').


5

> <> , 47 byte

Nguyên:

| v~" H e l l o ,   W o r l d ! "

~o<< ;!!!? l

Với mỗi ký tự thứ hai bị xóa:

|v"Hello, World!"
o<;!?l

Hãy thử chúng trực tuyến: bản gốc , sửa đổi

Chương trình ban đầu đẩy các nhân vật của "Xin chào, thế giới!" vào ngăn xếp (theo thứ tự ngược lại) xen kẽ với các khoảng trắng, sau đó lần lượt in một ký tự và xóa một ký tự cho đến khi chiều dài của ngăn xếp bằng không. Chương trình thứ hai thực hiện tương tự, ngoại trừ các hướng dẫn xóa ~đã biến mất.

Nếu bạn không ngại dừng lại với một lỗi, chúng ta có thể rút một lá khỏi cuốn Hồng y của Martin Ender : mã sửa đổi là

\"!dlroW ,olleH"!#o#

và bản gốc giống nhau nhưng có dòng mới được chèn giữa tất cả các ký tự, cho 39 byte. Hãy thử chúng trực tuyến: bản gốc , sửa đổi .


5

,,, 34 byte

 2"Hteoltlaol,l yWhourmladn!! "⟛

Khi xóa các ký tự được đánh số chẵn ...

 "Hello, World!"

Giải trình

Với tất cả các nhân vật:

 2"..."⟛

               no-op
 2             push 2 to the stack
  "..."        push "Hteoltlaol,l yWhourmladn!! " to the stack
       ⟛      pop 2 and the string and push every 2nd character of the string
               implicit output

Không có các ký tự được đánh số chẵn:

 "..."

               no-op
 "..."         push "Hello, World!" to the stack
               implicit output

5
Điều này ngụ ý bạn không cần phải nói điều này là không cạnh tranh.
FryAmTheEggman

2
Nhưng bạn phải giữ tất cả các ký tự được lập chỉ mục chẵn ... (0 chỉ mục) ...
HyperNeutrino

Rất tiếc, đã sửa. Chỉ cần thêm một nhân vật lol.
hoàn toàn là

4

Brainfuck, 155 byte

- - < - < < + [ + [ < + > - - - > - > - > - < < < ] > ] < < - - . < + + + + + + . < < - . . < < . < + . > > . > > . < < < . + + + . > > . > > - . < < < + .

Hãy thử trực tuyến!

Mỗi ký tự thứ hai bị xóa:

--<-<<+[+[<+>--->->->-<<<]>]<<--.<++++++.<<-..<<.<+.>>.>>.<<<.+++.>>.>>-.<<<+.

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.