Mở mã nguồn Hexagony


52

Giới thiệu

Nếu bạn không quen thuộc với Hexagony , thì đó là ngôn ngữ bí truyền được tạo bởi Martin Büttner. Điều này là ngôn ngữ này chấp nhận nhiều hình thức cho chương trình. Các chương trình sau đây đều tương đương:

abcdefg

 a b
c d e
 f g

Về cơ bản, mã đã được cuộn thành một hình lục giác thông thường. Nhưng lưu ý rằng việc thêm một lệnh mới vào mã, điều này abcdefghsẽ dẫn đến chương trình sau:

  a b c
 d e f g
h . . . .
 . . . .
  . . .

Như bạn có thể thấy, bước đầu tiên là cuộn mã thành một hình lục giác, và sau đó hình lục giác được điền với no-ops ( .) cho số lục giác trung tâm tiếp theo .

Nhiệm vụ của bạn rất đơn giản, khi được cung cấp một chuỗi (mã nguồn), xuất mã nguồn hình lục giác đầy đủ.

Những quy định

  • Bạn có thể cung cấp một chương trình hoặc một chức năng.
  • Khoảng trắng hàng đầu được cho phép, nhưng chỉ khi hình lục giác không ra khỏi hình dạng
  • Khoảng trống Trailing được cho phép.
  • Lưu ý rằng khoảng trắng trong chương trình được bỏ qua . Như vậy a b clà bằngabc
  • Chỉ các ký tự ASCII có thể in ( 32 - 126) được sử dụng, do đó chỉ Spacebỏ qua các ký tự thông thường .
  • Giả sử rằng độ dài của chuỗi lớn hơn 0.
  • Đây là , vì vậy bài nộp có số byte ít nhất sẽ thắng!

Các trường hợp thử nghiệm

Input: ?({{&2'2':{):!/)'*/

Output:
  ? ( {
 { & 2 '
2 ' : { )
 : ! / )
  ' * /


Input: H;e;l;d;*;r;o;Wl;;o;*433;@.>;23<\4;*/

Output:
   H ; e ;
  l ; d ; *
 ; r ; o ; W
l ; ; o ; * 4
 3 3 ; @ . >
  ; 2 3 < \
   4 ; * /


Input: .?'.) .@@/'/ .!.>   +=(<.!)}    (  $>( <%

Output:
   . ? ' .
  ) . @ @ /
 ' / . ! . >
+ = ( < . ! )
 } ( $ > ( <
  % . . . .
   . . . .

6
Ngoài ra, tôi không chắc liệu bạn có muốn trở nên kén chọn đó không, nhưng backticks bị bỏ qua trong quá trình xác định độ rộng mã vì chúng chú thích ký tự tiếp theo. Vì vậy, abc`defgthực sự sẽ trở thành pastebin.com/ZrdJmHiR
Martin Ender

2
@ MartinBüttner Ồ, tôi không biết điều đó :). Đối với thử thách này, backticks sẽ không được bỏ qua.
Ad Nam

18
Tôi thực sự muốn thấy một câu trả lời trong Hexagony cho câu hỏi này.
Arcturus

2
@Adnan Có lẽ một phản hồi tốt hơn sẽ là "Bạn có thể giả sử rằng đầu vào không chứa cờ gỡ lỗi ( `ký tự)."
Đi xe đạp

4
@Ampora Hỏi và bạn sẽ nhận được.
Martin Ender

Câu trả lời:


13

Bình thường, 57 54 50 49 48 46

V+UJfgh*6sUTlK-zd1_UtJ+*d-JNjd:.[K\.^TJZ=+Z+JN

Phòng thử nghiệm

In một không gian hàng đầu trên mỗi dòng.

Phiên bản này yêu cầu bằng chứng rằng 10 ^ n> = 3n (n - 1) + 1 với mọi n> = 1 . Cảm ơn ANerdIErickWong đã cung cấp bằng chứng.

Theo các bất đẳng thức sau: 10 ^ n> (1 + 3) ^ n = 1 + 3n + 9n (n - 1) + ...> 3n (n - 1) + 1 người ta có thể dễ dàng thấy rằng điều này đúng với n> = 2 . Kiểm tra trường hợp n = 1 khá tầm thường, cho 10> 1 .

Ngoài ra, lấy đạo hàm của các phương trình này hai lần cho thấy 10 ^ n có đạo hàm bậc hai lớn hơn cho tất cả n> = 1 , sau đó có thể được xếp tầng xuống các đạo hàm đầu tiên và cuối cùng là phương trình ban đầu.

Giải trình

              ##  Implicit: z=input(); Z=0
Jf...1        ##  Save to J the side length of the hexagon the code fills up
              ##  by finding the first number such that:
gh*6sUT       ##  the the T'th hexagonal number is greater than...
              ##  Computes 6 * T'th triangular number (by using sum 1..T-1) + 1
    lK-zd     ##  ...the length of the code without spaces (also save the string value to K)
V+UJ_UtJ      ##  For loop over N = [0, 1, ..., J-1, ..., 0]:
+*d-JN        ##  append J - N spaces to the front of the line
jd            ##  riffle the result of the next operation with spaces
:.[K\.yJ      ##  slice the string given by K padded to be the length of the Jth hexagon
              ##  number with noops
Z=+Z+JN       ##  from Z to Z + J + N, then set Z to be Z + J + N

2
Trước tiên, bạn cần chứng minh rằng ln (10) * 10 ^ n> 6n-3 (các đạo hàm) cho n> = 1. Điều này thật dễ dàng, vì các đạo hàm của các biểu thức này là ln (10) ^ 2 10 ^ n và 6. Vì 10 ^ n đang tăng đơn điệu và 10 ^ 1> 6 * 1, 10 ^ n lớn hơn 6n-3 cho tất cả n> = 1. Bạn có thể sử dụng cùng một logic để hoàn thành bằng chứng cho 10 ^ n và 3n (n-1) +1.
Arcturus

@Ampora Cảm ơn, tôi đã cân nhắc sử dụng các công cụ phái sinh, nhưng có vẻ như ô uế. Tôi không thể tìm thấy một cách tốt hơn mặc dù, rất nhiều đánh giá cao!
FryAmTheEggman

Vui mừng được giúp đỡ. Calc đôi khi có thể trở nên xấu xí.
Arcturus

trong liên kết pyth.herokuapp.com/?code=etc ở trên tôi thấy trình biên dịch không chạy ...
RosLuP

1
@FryAmTheEggman Có một cách rất dễ dàng để hiển thị giới hạn mạnh hơn nhiều 4 ^ n> 3n (n-1) + 1 cho n> = 1, không cần tính toán. Chỉ cần sử dụng thực tế là (1 + 3) ^ n = 1 + 3n + 9n (n-1) / 2 + ... bằng cách mở rộng nhị thức. Các điều khoản thứ nhất và thứ ba trực tiếp chuyên ngành 1 + 3n (n-1), do đó, bất đẳng thức là ngay lập tức nếu thuật ngữ thứ ba tồn tại (nghĩa là, với n> = 2). Điều này chỉ để lại trường hợp n = 1 không đáng kể vì RHS là 1.
Erick Wong

90

Lục giác , 271 byte

Tôi giới thiệu với bạn, 3% đầu tiên của trình thông dịch tự Hexagony ...

|./...\..._..>}{<$}=<;>'<..../;<_'\{*46\..8._~;/;{{;<..|M..'{.>{{=.<.).|.."~....._.>(=</.\=\'$/}{<}.\../>../..._>../_....@/{$|....>...</..~\.>,<$/'";{}({/>-'(<\=&\><${~-"~<$)<....'.>=&'*){=&')&}\'\'2"'23}}_}&<_3.>.'*)'-<>{=/{\*={(&)'){\$<....={\>}}}\&32'-<=._.)}=)+'_+'&<

Hãy thử trực tuyến! Bạn cũng có thể tự chạy nó, nhưng sẽ mất khoảng 5-10 giây.

Về nguyên tắc, điều này có thể phù hợp với độ dài 9 bên (cho số điểm từ 217 trở xuống), bởi vì điều này chỉ sử dụng 201 lệnh và phiên bản không được viết mà tôi đã viết trước (trên chiều dài 30) chỉ cần 178 lệnh. Tuy nhiên, tôi khá chắc chắn rằng sẽ mất nhiều thời gian để thực sự làm mọi thứ phù hợp, vì vậy tôi không chắc liệu tôi có thực sự thử nó hay không.

Cũng có thể chơi golf này một chút trong kích thước 10 bằng cách tránh sử dụng một hoặc hai hàng cuối cùng, để có thể bỏ qua các dấu không có dấu, nhưng điều đó đòi hỏi phải viết lại đáng kể, như một trong những đường dẫn đầu tiên tham gia sử dụng góc dưới bên trái.

Giải trình

Hãy bắt đầu bằng cách mở mã và chú thích các đường dẫn luồng điều khiển:

nhập mô tả hình ảnh ở đây

Điều đó vẫn còn khá lộn xộn, vì vậy đây là sơ đồ tương tự cho mã "không được mã hóa" mà tôi đã viết đầu tiên (trên thực tế, đây là chiều dài 20 và ban đầu tôi đã viết mã ở độ dài 30 nhưng nó rất thưa thớt Không cải thiện khả năng đọc, vì vậy tôi đã nén nó chỉ một chút để làm cho kích thước hợp lý hơn một chút):

nhập mô tả hình ảnh ở đây
Nhấn vào đây để xem phiên bản lớn hơn.

Các màu hoàn toàn giống nhau ngoài một vài chi tiết rất nhỏ, các lệnh không điều khiển luồng cũng hoàn toàn giống nhau. Vì vậy, tôi sẽ giải thích cách thức hoạt động của nó dựa trên phiên bản không được chỉnh sửa và nếu bạn thực sự muốn biết cách chơi golf, bạn có thể kiểm tra phần nào tương ứng với phần nào trong hình lục giác lớn hơn. (Điểm hấp dẫn duy nhất là mã đánh gôn bắt đầu bằng gương để mã thực tế bắt đầu ở góc phải sang trái.)

Thuật toán cơ bản gần giống với câu trả lời của tôi . Có hai điểm khác biệt:

  • Thay vì giải phương trình số lục giác trung tâm, tôi chỉ tính các số lục giác trung tâm liên tiếp cho đến khi một số bằng hoặc lớn hơn độ dài của đầu vào. Điều này là do Hexagony không có cách đơn giản để tính căn bậc hai.
  • Thay vì đệm ngay đầu vào bằng no-ops ngay lập tức, tôi kiểm tra sau nếu tôi đã sử dụng hết các lệnh trong đầu vào và in .thay thế nếu tôi có.

Điều đó có nghĩa là ý tưởng cơ bản nắm bắt được:

  • Đọc và lưu trữ chuỗi đầu vào trong khi tính toán độ dài của nó.
  • Tìm chiều dài cạnh nhỏ nhất N(và số lục giác trung tâm tương ứng hex(N)) có thể chứa toàn bộ đầu vào.
  • Tính đường kính 2N-1.
  • Đối với mỗi dòng, tính toán thụt lề và số lượng ô (tính tổng 2N-1). In thụt lề, in các ô (sử dụng .nếu đầu vào đã hết), in một nguồn cấp dữ liệu.

Lưu ý rằng chỉ có no-op nên mã thực tế bắt đầu ở góc bên trái (cái $, nhảy qua >, vì vậy chúng ta thực sự bắt đầu trên ,con đường màu xám đen).

Đây là lưới bộ nhớ ban đầu:

nhập mô tả hình ảnh ở đây

Vì vậy, con trỏ bộ nhớ bắt đầu trên cạnh đầu vào có nhãn , chỉ về phía Bắc. ,đọc một byte từ STDIN hoặc -1nếu chúng ta nhấn EOF vào cạnh đó. Do đó, <quyền sau là điều kiện cho dù chúng ta đã đọc tất cả các đầu vào. Bây giờ chúng ta hãy ở trong vòng lặp đầu vào. Mã tiếp theo chúng tôi thực hiện là

{&32'-

Điều này ghi 32 vào không gian được dán nhãn cạnh , và sau đó trừ nó khỏi giá trị đầu vào trong cạnh có nhãn diff . Lưu ý rằng điều này không bao giờ có thể âm bởi vì chúng tôi đảm bảo rằng đầu vào chỉ chứa ASCII có thể in được. Nó sẽ bằng không khi đầu vào là một khoảng trắng. (Như Timwi chỉ ra, điều này vẫn hoạt động nếu đầu vào có thể chứa các dòng hoặc tab, nhưng nó cũng sẽ loại bỏ tất cả các ký tự không thể in khác có mã ký tự nhỏ hơn 32.) Trong trường hợp đó, <làm chệch hướng con trỏ lệnh (IP) và con đường màu xám nhạt được thực hiện. Đường dẫn đó chỉ đơn giản là đặt lại vị trí của MP {=và sau đó đọc ký tự tiếp theo - do đó, khoảng trắng được bỏ qua. Mặt khác, nếu ký tự không phải là khoảng trắng, chúng ta thực thi

=}}})&'+'+)=}

Điều này đầu tiên di chuyển xung quanh hình lục giác thông qua cạnh chiều dài cho đến khi nó đối diện với cạnh khác , với =}}}. Sau đó, nó sao chép giá trị từ đối diện cạnh chiều dài vào cạnh chiều dài và tăng nó với )&'+'+). Chúng ta sẽ thấy trong một giây tại sao điều này có ý nghĩa. Cuối cùng, chúng tôi di chuyển một cạnh mới với =}:

nhập mô tả hình ảnh ở đây

(Các giá trị cạnh cụ thể là từ trường hợp thử nghiệm cuối cùng được đưa ra trong thử thách.) Tại thời điểm này, vòng lặp lặp lại, nhưng với mọi thứ đã dịch chuyển một hình lục giác về phía đông bắc. Vì vậy, sau khi đọc một nhân vật khác, chúng ta nhận được điều này:

nhập mô tả hình ảnh ở đây

Bây giờ bạn có thể thấy rằng chúng ta đang dần viết đầu vào (trừ khoảng trắng) dọc theo đường chéo phía đông bắc, với các ký tự ở mọi cạnh khác và độ dài cho đến ký tự đó được lưu trữ song song với chiều dài được dán nhãn .

Khi chúng ta hoàn thành vòng lặp đầu vào, bộ nhớ sẽ trông như thế này (nơi tôi đã gắn nhãn một vài cạnh mới cho phần tiếp theo):

nhập mô tả hình ảnh ở đây

Đây %là ký tự cuối cùng chúng ta đọc, 29là số lượng ký tự không phải không gian chúng ta đọc. Bây giờ chúng tôi muốn tìm chiều dài của hình lục giác. Đầu tiên, có một số mã khởi tạo tuyến tính trong đường dẫn màu lục / xám đậm:

=&''3{

Ở đây, =&sao chép chiều dài (29 trong ví dụ của chúng tôi) vào chiều dài được dán nhãn . Sau đó ''3di chuyển đến cạnh có nhãn 3 và đặt giá trị của nó thành 3(mà chúng ta chỉ cần là hằng số trong tính toán). Cuối cùng {di chuyển đến cạnh có nhãn N (N-1) .

Bây giờ chúng ta vào vòng lặp màu xanh. Vòng lặp này tăng N(được lưu trữ trong ô có nhãn N ) sau đó tính số lục giác ở giữa và trừ nó khỏi độ dài đầu vào. Mã tuyến tính thực hiện điều đó là:

{)')&({=*'*)'-

Ở đây, {)di chuyển đến và gia số N . ')&(di chuyển đến cạnh có nhãn N-1 , sao chép Nở đó và giảm nó. {=*tính sản phẩm của họ theo N (N-1) . '*)nhân số đó với hằng số 3và tăng kết quả trong cạnh có nhãn hex (N) . Theo dự kiến, đây là số lục giác trung tâm thứ N. Cuối cùng '-tính toán sự khác biệt giữa đó và chiều dài đầu vào. Nếu kết quả là dương, độ dài cạnh chưa đủ lớn và vòng lặp lặp lại (trong đó }}di chuyển MP trở lại cạnh có nhãn N (N-1) ).

Khi độ dài cạnh đủ lớn, chênh lệch sẽ bằng 0 hoặc âm và chúng ta nhận được điều này:

nhập mô tả hình ảnh ở đây

Trước hết, bây giờ có đường dẫn màu xanh tuyến tính thực sự dài, thực hiện một số khởi tạo cần thiết cho vòng lặp đầu ra:

{=&}}}32'"2'=&'*){=&')&}}

Việc {=&bắt đầu bằng cách sao chép kết quả ở cạnh khác vào cạnh dài , vì sau này chúng ta cần một cái gì đó không tích cực ở đó. }}}32ghi 32 vào không gian được dán nhãn . '"2ghi một hằng số 2 vào cạnh không ghi trên diff . '=&bản sao N-1vào cạnh thứ hai với cùng một nhãn. '*)nhân nó lên 2 và tăng nó để chúng ta có được giá trị chính xác ở cạnh có nhãn 2N-1 ở trên cùng. Đây là đường kính của hình lục giác. {=&')&sao chép đường kính vào cạnh khác có nhãn 2N-1 . Cuối cùng }}di chuyển trở lại cạnh có nhãn 2N-1 ở trên cùng.

Chúng ta hãy dán lại các cạnh:

nhập mô tả hình ảnh ở đây

Cạnh chúng ta hiện đang ở (vẫn giữ đường kính của hình lục giác) sẽ được sử dụng để lặp qua các dòng của đầu ra. Các cạnh được gắn nhãn thụt lề sẽ tính toán có bao nhiêu khoảng trống cần thiết trên dòng hiện tại. Các ô có nhãn cạnh sẽ được sử dụng để lặp lại số lượng ô trong dòng hiện tại.

Bây giờ chúng ta đang trên con đường màu hồng tính toán thụt lề . ('-giảm các dòng lặp và trừ nó từ N-1 (vào cạnh thụt lề ). Nhánh màu xanh / xám ngắn trong mã chỉ đơn giản là tính mô-đun của kết quả ( ~phủ định giá trị nếu nó âm hoặc bằng 0 và không có gì xảy ra nếu nó dương). Phần còn lại của đường màu hồng là "-~{phép trừ vết lõm từ đường kính vào cạnh ô và sau đó di chuyển trở lại cạnh thụt .

Con đường màu vàng bẩn bây giờ in vết lõm. Nội dung vòng lặp thực sự chỉ là

'";{}(

Nơi '"di chuyển đến cạnh không gian , ;in nó, {}di chuyển trở lại thụt lề(giảm nó.

Khi chúng ta thực hiện xong, đường dẫn màu xám đen (thứ hai) sẽ tìm kiếm ký tự tiếp theo để in. Các =}di chuyển trong vị trí (có nghĩa là, trên các cạnh tế bào , chỉ về phía Nam). Sau đó, chúng tôi có một vòng lặp rất chặt {}, chỉ cần di chuyển xuống hai cạnh theo hướng Tây Nam, cho đến khi chúng tôi chạm vào cuối chuỗi được lưu trữ:

nhập mô tả hình ảnh ở đây

Lưu ý rằng tôi đã di chuyển một cạnh có EOF? . Khi chúng tôi đã xử lý ký tự này, chúng tôi sẽ làm cho cạnh đó trở nên âm, để {}vòng lặp sẽ chấm dứt ở đây thay vì lần lặp tiếp theo:

nhập mô tả hình ảnh ở đây

Trong mã, chúng ta ở cuối con đường màu xám đen, nơi 'di chuyển lùi một bước vào ký tự đầu vào. Nếu tình huống là một trong hai sơ đồ cuối cùng (nghĩa là vẫn còn một ký tự từ đầu vào mà chúng ta chưa in), thì chúng ta đang đi theo con đường màu xanh lá cây (cái dưới cùng, dành cho những người không tốt với màu xanh lá cây và màu xanh da trời). Điều đó khá đơn giản: ;in chính nhân vật. 'di chuyển đến cạnh không gian tương ứng vẫn giữ 32 từ trước đó và ;in không gian đó. Sau đó {~làm cho EOF của chúng tôi ? phủ định cho lần lặp tiếp theo, 'di chuyển lùi một bước để chúng ta có thể quay lại đầu phía tây bắc của chuỗi bằng một }{vòng lặp chặt chẽ khác . Mà kết thúc trên chiều dàiô (ô không dương dưới hex (N) . Cuối cùng }di chuyển trở lại cạnh ô .

Nếu chúng ta đã cạn kiệt đầu vào, thì vòng lặp tìm kiếm EOF là gì? sẽ thực sự chấm dứt ở đây:

nhập mô tả hình ảnh ở đây

Trong trường hợp đó, 'di chuyển lên ô dài và thay vào đó, chúng ta sẽ chọn đường dẫn màu xanh lam nhạt (trên cùng), in ra một chữ không có op. Mã trong nhánh này là tuyến tính:

{*46;{{;{{=

Người {*46;viết 46 vào cạnh có nhãn no-op và in nó (tức là một khoảng thời gian). Sau đó {{;di chuyển đến cạnh không gian và in nó. Việc {{=di chuyển trở lại cạnh các ô cho lần lặp tiếp theo.

Tại thời điểm này, các đường dẫn nối lại với nhau và làm (giảm cạnh của các ô . Nếu iterator chưa bằng 0, chúng ta sẽ chọn đường dẫn màu xám nhạt, chỉ đơn giản là đảo ngược hướng của MP =và sau đó đi tìm ký tự tiếp theo để in.

Mặt khác, chúng ta đã đi đến cuối dòng hiện tại và IP sẽ đi theo con đường màu tím thay thế. Đây là những gì lưới bộ nhớ trông giống như tại thời điểm đó:

nhập mô tả hình ảnh ở đây

Đường dẫn màu tím chứa điều này:

=M8;~'"=

Sự =đảo ngược hướng của MP một lần nữa. M8đặt giá trị của nó thành 778(vì mã ký tự M77và các chữ số sẽ tự nối với giá trị hiện tại). Điều này xảy ra 10 (mod 256), vì vậy khi chúng tôi in nó ;, chúng tôi nhận được một nguồn cấp dữ liệu. Sau đó ~làm cho cạnh âm trở lại, '"di chuyển trở lại cạnh đường=đảo ngược MP một lần nữa.

Bây giờ nếu cạnh đường bằng 0, chúng ta đã hoàn thành. IP sẽ đi theo con đường màu đỏ (rất ngắn), trong đó @chấm dứt chương trình. Mặt khác, chúng ta tiếp tục trên con đường màu tím lặp lại thành màu hồng để in một dòng khác.


Sơ đồ điều khiển được tạo bằng HexagonyColorer của Timwi's . Sơ đồ bộ nhớ được tạo bằng trình gỡ lỗi trực quan trong IDE bí truyền của anh ấy .


19
Tôi thấy mình nói điều này rất nhiều trên các câu trả lời của hexagony: Just whoa.
Conor O'Brien

5
Hả ... nhưng .. wat ... mind = blown
Adnan

Tôi hy vọng ai đó sẽ làm điều này và ... Wow. Tôi không nói nên lời. Thật tuyệt vời.
Arcturus

19
Bước hai - viết 97% khác. :)
ASCIIThenANSI

Bước ba - là câu trả lời với ít byte nhất.
Tom M

19

CJam, 56 52 50 48 byte

Suy nghĩ đầu tiên của tôi là "hey tôi đã có mã cho việc này!" Nhưng sau đó tôi không thể bận tâm để kéo các mảnh cần thiết lại với nhau từ mã Ruby, đặc biệt là vì chúng có vẻ không phù hợp để chơi gôn. Vì vậy, tôi đã thử một cái gì đó khác ở CJam ...

lS-{_,4*(3/mq:D1%}{'.+}wD{D(2/-z_S*D@-@/(S*N@s}/

Kiểm tra nó ở đây.

Giải trình

Một chút toán học về các số lục giác trung tâm đầu tiên. Nếu hình lục giác thông thường có độ dài cạnh N, thì nó sẽ chứa 3N(N-1)+1các ô, phải bằng chiều dài mã nguồn k. Chúng ta có thể giải quyết điều đó Nbởi vì đó là một phương trình bậc hai đơn giản:

N = 1/2 ± √(1/4 + (k-1)/3)

Chúng ta có thể bỏ qua gốc âm, vì điều đó mang lại một âm N. Để điều này có một giải pháp, chúng ta cần căn bậc hai là một nửa số nguyên. Hay nói cách khác, √(1 + 4(k-1)/3) = √((4k-1)/3)cần phải là một số nguyên (may mắn thay, số nguyên này xảy ra là đường kính D = 2N-1của hình lục giác, dù sao chúng ta cũng sẽ cần). Vì vậy, chúng ta có thể liên tục thêm một lần duy nhất .cho đến khi điều kiện đó được đáp ứng.

Phần còn lại là một vòng lặp đơn giản đặt ra hình lục giác. Một quan sát hữu ích cho phần này là các khoảng trắng trong vết lõm cộng với các khoảng trắng trong mã trong mỗi dòng cộng với đường kính.

lS-     e# Read input and remove spaces.
{       e# While the first block yields something truthy, evaluate the second...
  _,    e#   Duplicate the code and get its length k.
  4*(   e#   Compute 4k-1.
  3/    e#   Divide by 3.
  mq    e#   Take the square root.
  :D    e#   Store this in D, just in case we're done, because when we are, this happens
        e#   to be the diameter of the hexagon.
  1%    e#   Take modulo 1. This is 0 for integers, and non-zero for non-integers.
}{      e# ...
  '.+   e#   Append a no-op to the source code.
}w
D{      e# For every i from 0 to D-1...
  D(2/  e#   Compute (D-1)/2 = N, the side length.
  -z    e#   Subtract that from the current i and get its modulus. That's the size of the
        e#   indentation on this line.
  _S*   e#   Duplicate and get a string with that many spaces.
  D@-   e#   Subtract the other copy from D to get the number of characters of code
        e#   in the current line.
  @/    e#   Pull up the source code and split into chunks of this size.
  (S*   e#   Pull off the first chunk and riffle it with spaces.
  N     e#   Push a linefeed character.
  @s    e#   Pull up the remaining chunks and join them back into a single string.
}/

Hóa ra chúng ta không cần phải sử dụng số học kép (trừ căn bậc hai). Do nhân với 4, không có va chạm khi chia cho 3 và mong muốn ksẽ là lần đầu tiên mang lại một căn bậc hai số nguyên.


8

Perl, 203 200 198

bao gồm + 1 cho -p

s/\s//g;{($l=y///c)>($h=1+3*++$n*($n-1))&&redo}$s=$_.'.'x($h-$l);for($a=$n;$a<($d=2*$n-1);$a++){$s=~s/.{$a}/$&\n/,$s=reverse($s)for 0..1}$_=join$/,map{(' 'x abs($n-$i++-1)).$_}$s=~/\S+/g;s/\S/ $&/g

chạy như: echo abc | perl -p file.pl

Một cách tiếp cận rất ngây thơ:

#!/usr/bin/perl -p

s/\s//g;                            # ignore spaces and EOL etc.
{                                   # find the smallest hex number:
    ($l=y///c)                      # calc string length
    > ($h=1+3*++$n*($n-1))          # 
    && redo                         # (should use 'and', but..)
}

$s = $_                             # save $_ as it is used in the nested for
   . '.' x ($h-$l);                 # append dots to fill hexagon

for ( $a = $n; $a < ($d=2*$n-1); $a++ )
{
        $s=~s/.{$a}/$&\n/,          # split lines
        $s=reverse($s)              # mirror
    for 0..1                        # twice
}

$_ = join$/,                        # join using newline
map {                               # iterate the lines
    (' 'x abs($n-$i++-1)) .$_       # prepend padding
} $s=~/\S+/g;                       # match lines

s/\S/ $&/g                          # prepend spaces to characters
                                    # -p takes care of printing $_

  • cập nhật 200 lưu một phép gán biến di chuyển byte và 2 khác bằng cách bỏ qua cuối cùng ;; mã dưới 200 byte ngay bây giờ!
  • cập nhật 198 lưu 2 byte bằng cách sử dụng $s=~/\S+/gthay vìsplit/\n/,$s

7

JavaScript (ES6), 162 172

Chức năng ẩn danh

Kích thước hình lục giác được tìm thấy giải quyết phương trình từ wikipedia

3*n*(n-1)-1 = l

Công thức giải quyết cơ bản là

n = ceil(3+sqrt(12*l-3))/6)

Với một số đại số và một số xấp xỉ (thx đến @ user18655 cũng vậy), nó trở thành

n = trunc(sqrt(l/3-1/12)+1.4999....)
s=>eval("s=s.match(/\\S/g);m=n=Math.sqrt(s.length/3-1/12)+1.49999|0;p=o=``;for(i=n+n;--i;i>n?++m:--m)for(o+=`\n`+` `.repeat(n+n-m),j=m;j--;o+=` `)o+=s[p++]||`.`")

Dễ đọc hơn

s=>{
  s=s.match(/\S/g);
  m=n=Math.sqrt(s.length/3-1/12)+1.49999;
  p=o='';
  for(i=n+n; --i; i>n?++m:--m)
    for(o += '\n'+' '.repeat(n+n-m), j=m; j--; o += ' ')
      o+=s[p++]||'.';
  return o
}

Kiểm tra đoạn trích (toàn trang tốt hơn - thời gian chạy ~ 1 phút)

f=s=>eval("s=s.match(/\\S/g);m=n=Math.sqrt(s.length/3-1/12)+1.49999|0;p=o=``;for(i=n+n;--i;i>n?++m:--m)for(o+=`\n`+` `.repeat(n+n-m),j=m;j--;o+=` `)o+=s[p++]||`.`")

t=0;
r='0';
(T=_=>t++<816?(O.innerHTML=f(r=t%10+r),setTimeout(T,20)):0)()
pre { font-size: 66% }
<pre id=O></pre>


1
Bạn có thể sử dụng n=...+1-1e-9|0thay vì n=Math.ceil(...)để lưu 2 byte. Bạn cũng có thể đi ES7 và sử dụng **0.5thay vì Math.sqrtnhưng điều đó tùy thuộc vào bạn. Tôi thường chỉ giữ câu trả lời ES6 vì chúng hoạt động trong trình duyệt của tôi haha!
dùng81655

@ user81655 gợi ý tốt, cảm ơn
edc65

5

Pyth, 52 51 byte

Jfgh**3TtTl=H-zd1=+H*\.*lHTV+UJt_UJAcH]+JN+*-JNdjdG

Hãy thử trực tuyến. Bộ thử nghiệm.

Mỗi dòng có thêm một không gian hàng đầu, như được OP cho phép.

Giải trình

 f              1          |   find first number n for which
             -zd           |           remove spaces from input
           =H              |         put result in H
          l                |       length of input without spaces
  g                        |     is less than or equal to
   h**3TtT                 |       nth centered hexagonal number
J                          | put result (hexagon side length) in J
                           |
      *lHT                 |      ten times length of input without spaces
   *\.                     |   that amount of dots
=+H                        | append to H
                           |
  UJ                       |    numbers 0 up to side length - 1
 +  t_UJ                   |   add numbers side length - 2 down to 0
V                          | loop over result
            +JN            |       current loop number + side length
         cH]               |     split to two parts at that position
        A                  |   put parts to G and H
                 -JN       |       side length - current loop number - 1
                *   d      |     that many spaces
                     jdG   |     join code on the line (G) by spaces
               +           |   concatenate parts and print

5

Võng mạc , 161 byte

Cảm ơn FryAmTheEggman vì đã lưu 2 byte.

Câu trả lời này là không cạnh tranh. Retina đã thấy một vài cập nhật kể từ thử thách này và tôi khá chắc chắn rằng mình đang sử dụng một số tính năng mới hơn (mặc dù tôi chưa kiểm tra).

Số lượng byte giả định mã hóa ISO 8859-1. Dòng đầu tiên chứa một không gian duy nhất. Lưu ý rằng hầu hết các ·chấm thực sự là trung tâm (0xB7).

 

^
$._$*·¶
^·¶
¶
((^·|\2·)*)·\1{5}·+
$2·
^·*
$.&$* ·$&$&$.&$* 
M!&m`(?<=(?= *(·)+)^.*)(?<-1>.)+(?(1)!)|^.+$
+m`^( *·+)· *¶(?=\1)
$& 
·
 ·
O$`(·)|\S
$1
·
.
G-2`

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

Tốt...

Giải trình

Có vẻ như dễ dàng nhất để xây dựng bố cục trước tiên chỉ bằng một ký tự duy nhất ( ·trong trường hợp này) và sau đó điền vào bố cục kết quả với các ký tự đầu vào. Lý do chính cho điều này là việc sử dụng một ký tự cho phép tôi sử dụng các phản hồi và lặp lại ký tự, trong đó việc đưa ra đầu vào trực tiếp sẽ yêu cầu các nhóm cân bằng đắt tiền.

 

Mặc dù trông không giống lắm, nhưng giai đoạn đầu tiên này sẽ loại bỏ khoảng trắng khỏi đầu vào.

^
$._$*·¶

Chúng tôi bắt đầu bằng cách thêm vào một dòng bổ sung có chứa Mcác dấu chấm ở giữa, Mđộ dài của đầu vào (sau khi xóa khoảng trắng).

^·¶
¶

Nếu đầu vào là một ký tự đơn, chúng tôi sẽ xóa dấu chấm trung tâm đó một lần nữa. Đây là một trường hợp đặc biệt đáng tiếc không được bao gồm trong giai đoạn tiếp theo.

((^·|\2·)*)·\1{5}·+
$2·

Điều này sẽ tính toán độ dài cạnh yêu cầu Ntrừ 1. Đây là cách hoạt động: các số lục giác trung tâm có dạng 3*N*(N-1) + 1. Vì số tam giác là N*(N-1)/2, điều đó có nghĩa là số lục giác gấp sáu lần số tam giác cộng với 1. Điều đó thuận tiện vì khớp số tam giác (thực sự chỉ 1 + 2 + 3 + ... + N) trong một biểu thức chính quy khá dễ dàng với các tham chiếu chuyển tiếp. Các số (^·|\2·)*phù hợp với số tam giác lớn nhất nó có thể. Như một phần thưởng tuyệt vời, $2sau đó sẽ giữ chỉ số của số tam giác này. Để nhân nó với 6, chúng tôi bắt nó thành nhóm 1và ghép nó thêm 5 lần nữa. Chúng tôi đảm bảo có ít nhất hai cái nữa ·với ··+. Bằng cách này, chỉ số của số tam giác tìm thấy không tăng cho đến khi có một ký tự nhiều hơn số lục giác ở giữa.

Cuối cùng, trận đấu này cung cấp cho chúng tôi hai phần nhỏ hơn chiều dài cạnh của hình lục giác cần thiết trong nhóm $2, vì vậy chúng tôi viết nó trở lại cùng với một dấu chấm trung tâm nữa để có được N-1.

^·*
$.&$* ·$&$&$.&$* 

Điều này biến chuỗi N-1dấu chấm trung tâm của chúng ta thành N-1không gian, 2N-1dấu chấm trung tâm và N-1không gian khác . Lưu ý rằng đây là vết lõm tối đa, tiếp theo là đường kính của hình lục giác, tiếp theo là thụt đầu dòng một lần nữa.

M!&m`(?<=(?= *(·)+)^.*)(?<-1>.)+(?(1)!)|^.+$

Điều này dài một cách khó chịu, nhưng về cơ bản nó chỉ cung cấp cho chúng ta tất cả các kết quả trùng lặp , có độ 2N-1dài a) ký tự và trên dòng đầu tiên hoặc b) dòng thứ hai. Điều này mở rộng kết quả từ giai đoạn trước thành hình lục giác đầy đủ, nhưng thụt vào một cách kỳ lạ. Ví dụ: đầu vào 12345678chúng tôi sẽ nhận được:

  ···
 ····
·····
···· 
···  
12345678

Đây là lý do tại sao chúng ta cần phải nối thêm không gian trong giai đoạn trước.

+m`^( *·+)· *¶(?=\1)
$& 

Điều này sửa lỗi thụt dòng của các dòng sau trung tâm, bằng cách liên tục thụt vào bất kỳ dòng nào ngắn hơn trước đó (bỏ qua khoảng trắng ở cuối), vì vậy chúng tôi nhận được điều này:

  ···
 ····
·····
 ···· 
  ···  
12345678

Bây giờ chúng ta chỉ cần chèn một số khoảng trắng với

·
 ·

Cung cấp cho chúng tôi:

   · · ·
  · · · ·
 · · · · ·
  · · · · 
   · · ·  
12345678

Phù, thế là xong.

O$`(·)|\S
$1

Thời gian để điền chuỗi đầu vào vào các dấu chấm trung tâm. Điều này được thực hiện với sự giúp đỡ của một giai đoạn sắp xếp. Chúng tôi khớp tất cả các dấu chấm trung tâm và từng ký tự trên dòng cuối cùng và chúng tôi sắp xếp chúng theo kết quả của sự thay thế đã cho. Sự thay thế đó là trống cho các ký tự trên dòng cuối cùng và ·cho các dấu chấm trung tâm, vì vậy điều xảy ra là các chấm trung tâm được sắp xếp đơn giản đến cuối (vì sắp xếp ổn định). Điều này di chuyển các ký tự đầu vào vào vị trí:

   1 2 3
  4 5 6 7
 8 · · · ·
  · · · · 
   · · ·  
········

Chỉ còn hai điều nữa:

·
.

Điều này biến các chấm trung tâm thành các khoảng thời gian thường xuyên.

G-2`

Và điều này loại bỏ dòng cuối cùng.


1

JavaScript (ES6), 144 byte

(s,n=1,l=0,p=0,m=s.match(/\S/g))=>m[n]?f(s,n+6*++l,l):[...Array(l+l+1)].map((_,i,a)=>a.map((_,j)=>j<l-i|j<i-l?``:m[p++]||`.`).join` `).join`\n`

Trường hợp \nđại diện cho nhân vật dòng chữ mới. Sử dụng một kỹ thuật để tạo ra một hình lục giác mà trước đây tôi đã sử dụng trên một số câu trả lời dạng khác . Đối với ES7, căn bậc hai hoạt động ngắn hơn một chút so với phương pháp đệ quy:

(s,p=0,m=s.match(/\S/g),l=(~-m.length/3)**.5+.5|0)=>[...Array(l+l+1)].map((_,i,a)=>a.map((_,j)=>j<l-i|j<i-l?``:m[p++]||`.`).join` `).join`\n`

1

Python 3 , 144 byte

c=input().replace(' ','')
n=x=1
while x<len(c):x+=n*6;n+=1
c=c.ljust(x,'.')
while c:print(' '*(x-n)+' '.join(c[:n]));c=c[n:];n-=(len(c)<x/2)*2-1

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

Điều này sử dụng một lượng khoảng trắng hàng đầu khá khác nhau cho các hình lục giác có kích thước khác nhau, nhưng hình dạng chung vẫn tồn tại.

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.