Розгортання вихідного коду шестикутника


52

Вступ

Якщо ви не знайомі з Гексагоні , це езотерична мова, яку створив Мартін Бюттнер. Вся справа в тому, що ця мова приймає кілька форм для програми. Наступні програми еквівалентні:

abcdefg

і

 a b
c d e
 f g

Таким чином, код згорнутий у звичайний шестикутник. Але зауважте, що додавання нової команди до коду, що abcdefghпризведе до наступної програми:

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

Як бачимо, перший крок - це зведення коду до шестикутника, а після цього шестикутник заповнюється no-ops ( .) до наступного по центру центрального шестикутника .

Ваше завдання просте: якщо вам надано рядок (вихідний код), виведіть повний шестикутник вихідного коду.

Правила

  • Ви можете надати програму або функцію.
  • Провідна пробільна зона дозволена, але лише тоді, коли шестикутник не вийде з форми
  • Доступний пробіл пробігу дозволений.
  • Зауважте, що пробіли в програмі ігноруються . Так a b cдорівнюєabc
  • Використовуються лише символи ASCII для друку ( 32 - 126), тому Spaceігнорується лише звичайний символ.
  • Припустимо, що довжина рядка більше 0.
  • Це , тому подання з найменшою кількістю байтів виграє!

Тестові справи

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
Крім того, я не впевнений, чи хочете ви бути такими вибагливими, але зворотні посилання ігноруються в процесі визначення ширини коду, оскільки вони анотують наступний символ. Так abc`defgби насправді стати pastebin.com/ZrdJmHiR
Мартін Ендер

2
@ MartinBüttner О, я цього не знав :). У цьому виклику задні посилання не будуть ігноровані.
Аднан

18
Я дуже хочу побачити відповідь у Гексагонії на це запитання.
Арктур

2
@Adnan Можливо, кращою відповіддю буде "Ви можете припустити, що на вході немає прапорів ( `символів) налагодження ."
Рікінг

4
@Ampora Запитайте, і ви отримаєте.
Мартін Ендер

Відповіді:


13

Піта, 57 54 50 49 48 46

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

Тестовий сюїт

Друкує провідний пробіл у кожному рядку.

Ця версія вимагає доказу, що 10 ^ n> = 3n (n - 1) + 1 для всіх n> = 1 . Дякуємо ANerdI та ErickWong за надані докази.

Дотримуючись цих нерівностей: 10 ^ n> (1 + 3) ^ n = 1 + 3n + 9n (n - 1) + ...> 3n (n - 1) + 1 можна легко побачити, що це правильно для n> = 2 . Дослідження випадку n = 1 є досить тривіальним, даючи 10> 1 .

Альтернативно, введення похідних цих рівнянь двічі показує, що 10 ^ n має більшу другу похідну для всіх n> = 1 , яка потім може бути каскадно зменшена до перших похідних і, нарешті, до початкових рівнянь.

Пояснення

              ##  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
Спочатку потрібно довести, що ln (10) * 10 ^ n> 6n-3 (похідні) при n> = 1. Це легко, оскільки похідні цих виразів ln (10) ^ 2 10 ^ n і 6. Оскільки 10 ^ n монотонно зростає і 10 ^ 1> 6 * 1, 10 ^ n більше, ніж 6n-3 для всіх n> = 1. Ви можете використовувати ту саму логіку, щоб завершити доведення для 10 ^ n та 3n (n-1) +1.
Арктур

@Ampora Спасибі, я думав використовувати похідні, але це здавалося нечистим. Я не зміг знайти кращого способу, але так високо оцінений!
FryAmTheEggman

Радий допомогти. Кальц іноді може бути справді некрасивим.
Арктур

за посиланням pyth.herokuapp.com/?code=etc вище, я знаходжу компілятор не запускається ...
RosLuP

1
@FryAmTheEggman Існує дуже простий спосіб показати набагато сильніший зв'язаний 4 ^ n> 3n (n-1) + 1 для n> = 1, обчислення не потрібно. Просто використовуйте той факт, що (1 + 3) ^ n = 1 + 3n + 9n (n-1) / 2 + ... шляхом двочленного розширення. Перший і третій доданки безпосередньо мажоризують 1 + 3n (n-1), тому нерівність є негайною, якщо існує третій член (тобто для n> = 2). Це залишає лише випадок n = 1, який є тривіальним, оскільки РШС 1.
Ерік Вонг,

90

Шестикутник , 271 байт

Представляю вашій увазі перші 3% самоперекладача шестикутників ...

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

Спробуйте в Інтернеті! Ви також можете запустити його на себе, але це займе близько 5-10 секунд.

В принципі, це може вписатись у бічну довжину 9 (для оцінки 217 або менше), оскільки для цього використовується лише 201 команда, а для неперевершеної версії, яку я написав спочатку (на стороні 30), потрібно було лише 178 команд. Однак я майже впевнений, що для того, щоб все було правильно, знадобиться назавжди, тому я не впевнений, чи дійсно я спробую це зробити.

Слід також мати можливість пограти в гольф трохи розміром 10, уникаючи використання останніх одного чи двох рядів, таким чином, щоб пропуски не можна було опустити, але це вимагало б істотного переписування, як одного з перших шляхів приєднується використовує нижній лівий кут

Пояснення

Почнемо з розгортання коду та анотації контурів потоку управління:

введіть тут опис зображення

Це все ще безладно, тому ось така ж схема для коду, що не використовується для "без вологів", який я написав спочатку (насправді це довжина бічної сторони 20, і спочатку я написав код на 30-бічній стороні, але це було настільки рідко, що він би не взагалі не покращую читабельність, тому я її трохи ущільнив, щоб зробити розмір трохи розумнішим):

введіть тут опис зображення
Клацніть для збільшення версії.

Кольори абсолютно однакові, окрім кількох дуже незначних деталей, команди, які не контролюють потік, також точно однакові. Тож я поясню, як це працює за версією, що не використовується для гольфу, і якщо ви дійсно хочете дізнатися, як працює гольф, ви можете перевірити, які деталі там відповідають, а які у великому шестикутнику. (Єдина уловка полягає в тому, що гольф-код починається з дзеркала, так що фактичний код починається в правому куті, ідучи ліворуч.)

Основний алгоритм майже ідентичний моїй відповіді CJam . Є дві відмінності:

  • Замість того, щоб розв'язувати рівняння по центру з шестикутним числом, я просто обчислював послідовні центрировані шестикутні числа, поки одне не дорівнює або не перевищує довжину вводу. Це тому, що в шестикутника немає простого способу обчислити квадратний корінь.
  • Замість того, щоб одразу вкладати вхід без операцій, я перевіряю пізніше, чи я вже вичерпав команди на вході, і надрукував .а, якщо є.

Це означає, що основна ідея зводиться до:

  • Прочитайте та зберігайте вхідний рядок, обчислюючи його довжину.
  • Знайдіть найменшу бічну довжину N(і відповідне по центру шестикутне число hex(N)), яка може вмістити весь вхід.
  • Обчисліть діаметр 2N-1.
  • Для кожного рядка обчисліть відступ та кількість комірок (які підсумовують 2N-1). Роздрукуйте відступ, надрукуйте клітинки (використовуючи, .якщо вхід уже вичерпано), надрукуйте подачу рядків.

Зауважте, що немає лише опісів, тому власне код починається в лівому куті (той $, який перестрибує через >, тому ми дійсно починаємо з ,темно-сірого шляху).

Ось початкова сітка пам'яті:

введіть тут опис зображення

Таким чином, вказівник пам'яті починається на крайовому вході , вказуючи на північ. ,читає байт зі STDIN або a, -1якщо ми потрапили EOF в цей край. Отже, <відразу після цього є умовою того, чи ми прочитали всі матеріали. Залишимося зараз у циклі введення. Наступний код, який ми виконуємо, - це

{&32'-

Це записує 32 в простір , позначений ребром , а потім віднімає його від вхідного значення в краю, позначеному diff . Зауважте, що це ніколи не може бути негативним, оскільки ми гарантуємо, що вхід містить лише друкований ASCII. Це буде нуль, коли на вході був пробіл. (Як зазначає Тімві, це все одно спрацювало, якби вхід міг містити канали ліній або вкладки, але він також викреслив би всі інші недруковані символи з кодами символів менше 32.) У цьому випадку <відхиляється вказівник інструкції (IP) зліва і йде світло-сірий шлях. Цей шлях просто скидає положення MP з, {=а потім читає наступний символ - таким чином, пропуски пропускаються. В іншому випадку, якщо персонаж не був пробілом, ми виконуємо

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

Це спочатку рухається навколо шестикутника через край довжини до його протилежного краю різниці , з =}}}. Потім він копіює значення з навпроти довжини кромки в довжину краю, а також збільшує його з )&'+'+). Ми побачимо через секунду, чому це має сенс. Нарешті, пересуваємо новий край за допомогою =}:

введіть тут опис зображення

(Конкретні значення ребра припадають на останній тестовий випадок, поданий у виклику.) На цьому етапі цикл повторюється, але зі всім зміщенням одного шестикутника на північний схід. Отже, прочитавши іншого персонажа, ми отримуємо це:

введіть тут опис зображення

Тепер ви можете бачити, що ми поступово пишемо введення (мінус пробіли) по діагоналі північного сходу, з символами на кожному іншому краї, а довжина до цього символу зберігається паралельно довжині ребра .

Коли ми закінчимося з циклом введення, пам'ять буде виглядати приблизно так (де я вже позначив кілька нових ребер для наступної частини):

введіть тут опис зображення

%Є останнім символом ми читаємо, то 29є число символів без пробілів ми читаємо. Тепер ми хочемо знайти бічну довжину шестикутника. По-перше, є деякий лінійний код ініціалізації у темно-зеленому / сірому шляху:

=&''3{

Тут =&скопіюємо довжину (29 у нашому прикладі) у крайку, позначену довжиною . Потім ''3переходить до краю, позначеного 3, і встановлює його значення 3(яке нам просто потрібно як константа в обчисленні). Нарешті {рухається до краю, позначеного N (N-1) .

Тепер вводимо синю петлю. Цей приріст циклу N(зберігається у комірці з позначкою N ) потім обчислює його центроване шестикутне число і віднімає його від вхідної довжини. Лінійний код, який робить це:

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

Тут, {)переміщається і збільшує N . ')&(переходить до краю, позначеного N-1 , копіює Nйого та зменшує його. {=*обчислює їх добуток у N (N-1) . '*)множиться на те, що на постійні 3та збільшення кроків виходить шестигранник, позначений краєм (N) . Як і очікувалося, це N-центр по шестикутній кількості. Нарешті '-обчислює різницю між цією та довжиною введення. Якщо результат позитивний, довжина сторони ще недостатньо велика, і петля повторюється (де }}пересуньте МП назад до краю, позначеного N (N-1) ).

Як тільки довжина сторони буде достатньо великою, різниця буде нульовою або негативною, і ми отримаємо наступне:

введіть тут опис зображення

По-перше, зараз існує дійсно довгий лінійний зелений шлях, який робить певну необхідну ініціалізацію для вихідного циклу:

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

В {=&починається з копіюванням результату в диффе краю в довжині край, тому що пізніше потрібно що - то непозитивним там. }}}32записує 32 в пробіл, позначений краєм . '"2записує константу 2 в неозначений край над розд . '=&копії N-1на другий край з тією ж міткою. '*)помножуємо його на 2 і збільшуємо його, так що ми отримуємо правильне значення в краю, позначеному вгорі 2N-1 . Це діаметр шестикутника. {=&')&копіює діаметр в інший край, позначений 2N-1 . Нарешті, }}повертається назад до краю з позначкою 2N-1 вгорі.

Розберемо ребра:

введіть тут опис зображення

Край, на якому ми перебуваємо в даний момент (який досі має діаметр шестикутника), буде використаний для перебору ліній виводу. Ребро з міткою відступ буде обчислити , скільки простору необхідно на поточному рядку. Клітини, позначені краєм, будуть використовуватися для ітерації над кількістю комірок у поточному рядку.

Зараз ми на рожевій стежці, яка обчислює відступ . ('-зменшує ітератор рядків і віднімає його від N-1 (до краю відступу ). Коротка синя / сіра гілка в коді просто обчислює модуль результату ( ~заперечує значення, якщо воно негативне або нульове, і нічого не відбувається, якщо воно є позитивним). Решта рожевого контуру - "-~{це віднімання відступу від діаметра до краю комірок, а потім переміщення назад до краю відступу .

Зараз брудно-жовтий шлях друкує відступ. Вміст циклу справді просто

'";{}(

Там, де '"рухається до простору , ;друкується, {}повертається до відступу і (зменшує його.

Коли ми закінчимо з цим, (другий) темно-сірий шлях шукає наступного символу для друку. В =}переміщається в положення (що означає, на клітини краю, що вказують на південь). Тоді у нас дуже щільна петля, {}яка просто рухається вниз по двох краях в напрямку Південний Захід, поки ми не потрапимо в кінець збереженої рядки:

введіть тут опис зображення

Зауважте, що я відновив один край там EOF? . Після обробки цього символу ми зробимо цей край негативним, так що {}цикл закінчиться тут замість наступної ітерації:

введіть тут опис зображення

У коді ми знаходимося в кінці темно-сірого шляху, де 'рухаємось на один крок назад на вхідний символ. Якщо ситуація є однією з двох останніх діаграм (тобто є ще символ із введення, який ми ще не надрукували), то ми беремо зелений шлях (нижній, для людей, які не вподобають зелений та синій). Це досить просто: ;друкує самого персонажа. 'переміщується до відповідного крайового простору, який все ще містить 32 з попереднього, і ;друкує цей простір. Тоді {~робить наш EOF? мінус для наступної ітерації, 'відсуває крок назад, щоб ми могли повернутися до північно-західного кінця рядка ще однією щільною }{петлею. Який закінчується по довжиніклітинку ( непозитивну, розташовану нижче шістнадцяткової (N) . Нарешті, }повертається назад до краю комірок) .

Якщо ми вже вичерпали вхід, то цикл, який шукає EOF? фактично припиняється тут:

введіть тут опис зображення

У цьому випадку 'рухається до комірки довжини , і ми замість цього беремо світло-блакитний (верхній) шлях, який друкує неоперативний варіант. Код у цій галузі лінійний:

{*46;{{;{{=

Запис {*46;46 у край, позначений no-op, і друкує його (тобто період). Потім {{;рухається до крайового простору і друкує це. В {{=рухається назад до клітинам краю для наступної ітерації.

У цей момент шляхи з'єднуються назад і (зменшують краю комірок . Якщо ітератор ще не дорівнює нулю, ми підемо світло-сірим шляхом, який просто переверне напрямок MP =і далі піде на друк наступного символу.

В іншому випадку ми дійшли до кінця поточного рядка, і IP замість цього скористається фіолетовим шляхом. Ось як виглядає сітка пам'яті в цей момент:

введіть тут опис зображення

Фіолетовий шлях містить це:

=M8;~'"=

=Знову змінює напрямок МП. M8встановлює набори своїм значенням 778(оскільки код символу Mє 77і цифри додаватимуть себе до поточного значення). Це трапляється 10 (mod 256)так, коли ми друкуємо його ;, ми отримуємо лінійку передач. Потім ~знов робить край негативним, '"повертається до краю рядків і =ще раз повертає MP.

Тепер, якщо край рядків дорівнює нулю, ми закінчили. IP буде проходити (дуже короткий) червоний шлях, де @програма припиняється. В іншому випадку ми продовжуємо пурпуровий шлях, який замикається назад на рожевий, щоб надрукувати ще один рядок.


Діаграми керування потоком, створені за допомогою шестигранника Colour Timwi . Діаграми пам'яті, створені за допомогою візуального відладчика в його Езотеричному IDE .


19
Я вважаю, що це багато говорять на відповіді шестикутників: Просто що.
Conor O'Brien

5
Гм ... але .. ват ... розум = видув
Аднан

Я сподівався, що хтось це зробить і ... Нічого собі. Я втратив дар мови. Це круто.
Арктур

19
Крок другий - запишіть інші 97%. :)
ASCIIThenANSI

Крок третій - як відповідь з найменшими байтами.
Том М

19

CJam, 56 52 50 48 байт

Перша моя думка була: "Ей, у мене вже є код для цього!" Але тоді я не міг потрудитися витягти необхідні шматки разом із коду Рубі, тим більше, що вони не здавалися дуже придатними для того, щоб грати в гольф. Тому я спробував щось інше в CJam ...

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

Перевірте це тут.

Пояснення

Спочатку трохи математики про централізовані шестикутні цифри. Якщо звичайний шестикутник має бічну довжину N, то він буде містити 3N(N-1)+1комірки, які повинні дорівнювати довжині вихідного коду k. Ми можемо це вирішити, Nоскільки це просте квадратичне рівняння:

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

Ми можемо ігнорувати негативний корінь, оскільки це дає від'ємний N. Для того, щоб мати рішення, нам потрібен квадратний корінь з півцілим числом. Або іншими словами, √(1 + 4(k-1)/3) = √((4k-1)/3)повинно бути ціле число (на щастя, це ціле число трапляється діаметром D = 2N-1шестикутника, який нам все одно знадобиться). Тож ми можемо неодноразово додавати сингл, .поки ця умова не буде виконана.

Решта - це проста петля, яка розкладає шестикутник. Корисним спостереженням для цієї частини є те, що пробіли в відступі плюс непробіли в коді в кожному рядку дорівнюють діаметру.

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.
}/

Виявляється, нам зовсім не потрібно використовувати подвійну арифметику (крім квадратного кореня). Через множення на 4 не виникає зіткнень при діленні на 3, і бажаний kбуде першим, щоб отримати цілий квадратний корінь.


8

Perl, 203 200 198

включає + 1 для -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

працювати як: echo abc | perl -p file.pl

Дуже наївний підхід:

#!/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 $_

  • оновлення 200 збереження байтового переміщення змінної призначення та ще 2, опустивши остаточне ;; код зараз під 200 байтами!
  • оновлення 198 зберегти 2 байти, використовуючи $s=~/\S+/gзамістьsplit/\n/,$s

7

JavaScript (ES6), 162 172

Анонімна функція

Розмір шестикутника знайдеться для вирішення рівняння з Вікіпедії

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

Формула вирішення в основному

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

З деякою алгеброю і деяким наближенням (thx до @ user18655 теж) це стає

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++]||`.`")

Більш читабельний

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
}

Фрагмент тесту (краще повна сторінка - час роботи ~ 1 хвилина)

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
Ви можете використовувати n=...+1-1e-9|0замість того, n=Math.ceil(...)щоб зберегти 2 байти. Ви також можете перейти на ES7 і використовувати **0.5замість цього, Math.sqrtале це залежить від вас. Зазвичай я просто зберігаю свої відповіді ES6, оскільки вони працюють у моєму браузері, ха-ха!
користувач81655

@ user81655 гарний натяк, дякую
edc65

5

Pyth, 52 51 байт

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

Спробуйте в Інтернеті. Тестовий набір.

У кожному рядку є один додатковий провідний простір, дозволений ОП.

Пояснення

 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

Сітківка , 161 байт

Завдяки FryAmTheEggman за збереження 2 байтів.

Ця відповідь є неконкурентною. Retina побачила кілька оновлень після цього виклику, і я впевнений, що використовую деякі новіші функції (хоча я не перевіряв).

Кількість байтів передбачає кодування ISO 8859-1. Перший рядок містить єдиний пробіл. Зауважте, що більшість ·фактично є центральними крапками (0xB7).

 

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

Спробуйте в Інтернеті!

Ну...

Пояснення

Здається, найпростіше побудувати макет спочатку за допомогою лише одного символу ( ·у цьому випадку), а потім заповнити отриманий макет символами введення. Основні причини цього полягають у тому, що використання одного символу дозволяє мені використовувати зворотні посилання та повторення символів, коли викладення даних безпосередньо потребує дорогих балансуючих груп.

 

Хоча це виглядає не так вже й багато, цей перший етап видаляє пробіли з вводу.

^
$._$*·¶

Почнемо, попередньо додавши додатковий рядок, який містить Mцентральні крапки, де Mдовжина вводу (після видалення пробілів).

^·¶
¶

Якщо введення було одним символом, ми знову видаляємо цю центральну крапку. Це нещасний особливий випадок, який не охоплюється наступним етапом.

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

При цьому обчислюється необхідна довжина сторони Nмінус 1. Ось як це працює: централізовані шестикутні номери мають форму 3*N*(N-1) + 1. Оскільки трикутні числа є N*(N-1)/2, це означає, що шестикутні числа в шість разів перевищують трикутне число плюс 1. Це зручно, тому що зіставити трикутні числа (які насправді є просто 1 + 2 + 3 + ... + N) в регулярному виразі досить легко з прямими посиланнями. У (^·|\2·)*матчах самого велике трикутне число може. Як приємний бонус, $2тоді буде проведено індекс цього трикутного числа. Щоб помножити його на 6, ми збираємо його в групу 1і співставляємо ще 5 разів. Ми переконайтеся , що є принаймні ще два ·з ·і·+. Таким чином, індекс знайденого трикутного числа не збільшується, поки на один символ більше, ніж по центру, шестикутне число.

Зрештою, ця відповідність дає нам на дві менші довжини сторони необхідного шестикутника в групі $2, тому ми записуємо це назад разом із ще однією центральною крапкою N-1.

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

Це перетворює наш рядок N-1центральних точок у N-1пробіли, 2N-1центральні точки та інші N-1пробіли. Зауважте, що це максимальний відступ з подальшим діаметром шестикутника з подальшим повторним відступом.

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

Це неприємно довго, але в основному це просто дає нам всі збіги, що перекриваються , які є або а) 2N-1символами довгими і на першому рядку, або б) у другому рядку. Це розширює результат попереднього етапу на повний, але дивно розрізаний шестикутник. Наприклад, для введення 12345678ми отримаємо:

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

Ось чому нам потрібно було додавати пробіли і на попередньому етапі.

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

Це фіксує відступ ліній після центру, повторно відступаючи будь-яку лінію, яка коротша за попередню (ігноруючи пробіли), тому ми отримуємо це:

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

Тепер ми просто вставимо пробіли

·
 ·

Що дає нам:

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

Фу, це зроблено.

O$`(·)|\S
$1

Час для заповнення вхідного рядка в центральні точки. Це робиться за допомогою сортування етапу. Ми узгоджуємо всі центральні точки та кожного символу в останньому рядку, і сортуємо їх за результатами заданої підстановки. Ця заміна порожня для символів в останньому рядку та ·для центральних крапок, тож трапляється те, що центральні точки просто сортуються до кінця (оскільки сортування стабільне). Це переміщує символи введення на місце:

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

Зараз залишилось лише дві речі:

·
.

Це перетворює центральні точки в регулярні періоди.

G-2`

І це відкидає останній рядок.


1

JavaScript (ES6), 144 байти

(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`

Де \nпредставляє буквальний символ нового рядка. Використовує техніку для створення шестикутника, яку я раніше використовував у кількох інших відповідях на . Для ES7 отримання квадратних коренів працює трохи коротше, ніж рекурсивний підхід:

(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

Пітон 3 , 144 байти

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

Спробуйте в Інтернеті!

Тут використовується досить велика кількість пробільних пробілів для шестикутників різного розміру, але загальна форма зберігається.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.