Підрахунок Квіпу: База 10 у новому світі


41

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

Кожен кластер вузлів - це цифра, і є три основні типи вузлів: прості вузлові накладки; "довгі вузли", що складаються з накладного вузла з одним або декількома додатковими витками; і цифра-вісім вузлів.

  • Потужність десяти показана позицією вздовж струни, і це положення вирівняне між послідовними нитками.
  • Цифри в позиціях на 10 і вище потужностей представлені кластерами простих вузлів (наприклад, 40 - це чотири простих вузли поспіль у позиції "десятки").
  • Цифри в положенні «ті» представлені довгими вузлами (наприклад, 4 - вузол з чотирма витками). Через те, як зав'язуються вузли, цифра 1 не може бути показана таким чином і представлена ​​в цьому положенні фігурою восьми вузлів.
  • Нуль представлений відсутністю вузла у відповідному положенні.

Деталі

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

Вузли

Кожен вузол буде представлений одним символом ASCII.

  • . являє собою простий вузол
  • : являє собою один виток довгого вузла
  • 8 являє собою фігуру-вісім вузол
  • | являє собою відсутність вузла, а також роздільник між цифрами.

Побудова Кіпуса

Квіпу будуються відповідно до цих правил.

  1. Пасма рухаються зверху вниз у порядку зменшення (як, наприклад, цифра одиниць буде в нижньому кінці пасма). Цифри вздовж пасма розділені символом ( |).
  2. Потужність 10 цифр, що представляє цифру, визначається її положенням вздовж нитки, так само, як обчислюється потужність цифри 10, використовуючи її індекс у кількості в нашій системі числення. Тобто, 24з а 2в десятках і а 4в одиницях місце буде представлено двома вузлами, роздільником ( |), потім чотирма вузлами.
  3. Цифри в тому ж положенні вирівнюються до нижньої частини пасма. Якщо одна цифра в позиції матиме менше вузлів, ніж інші цифри інших чисел у цій же позиції, відсутність цих вузлів представлена ​​( |).
  4. Послідовні прості вузли ( .) представляють значення у своїй позиції.
  5. Кожна цифра представлена ​​щонайменше 1 символом. Коли значення цифр дорівнює 0 для всіх чисел у квапі, воно представляється відсутністю вузла ( |).
  6. Місце підрозділів обробляється спеціально. Місце в одиницях зображено цифрою вісім вузлів ( 8). Значення двох або більше в місці одиниць представлено послідовними довгими вузлами ( :).
  7. Коли цифра одиниць дорівнює 0 для всіх чисел у квапі, відсутність вузла не друкується, але тривалі розмежувач для десяткової цифри зберігається.
  8. Немає роздільника після цифри одиниць.

Правила

  • Введення складається з не порожнього списку невід’ємних цілих чисел, які можуть бути отримані за допомогою будь-якого з методів введення за замовчуванням . Ви можете припустити, що ці цілі числа є меншими або рівними 2147483647або 2^31-1. Хоча тестові випадки обмежені пробілом, ваш формат введення може відокремлювати введення будь-яким зручним для вашої мови способом, будь то розділене комами, розділене новою лінією, у масиві тощо.
  • Результат складається з єдиного Quipu, побудованого за правилами, описаними вище. Вихід може бути наданий за допомогою будь-якого з методів виводу за замовчуванням .
  • Ваш код повинен бути програмою або функцією, хоча це не має бути іменованою функцією.
  • Вузли потребують певного часу, щоб заощадити час, ваш код якомога коротший.

Як завжди, якщо проблема неясна, будь ласка, повідомте мене про це. Успіхів і хорошого гольфу!

Приклади

Вхід:

5 3 1 0

Вихід:

:|||
:|||
::||
::||
::8|

Вхід:

50 30 10 0

Вихід:

.|||
.|||
..||
..||
...|
||||

Вхід:

330

Вихід:

.
.
.
|
.
.
.
|

Вхід:

204 1

Вихід:

.|
.|
||
||
||
:|
:|
:|
:8

Вхід:

201 0 100 222

Вихід:

.||.
.|..
||||
|||.
|||.
||||
|||:
8||:

Вхід:

1073741823 2147483647

Вихід:

|.
..
||
|.
||
.|
.|
.|
..
..
..
..
||
|.
|.
|.
|.
..
..
..
||
.|
.|
.|
..
..
..
..
||
|.
|.
|.
|.
..
..
..
..
||
|.
|.
..
||
.|
.|
..
..
..
..
..
..
||
|.
|.
..
..
||
|:
|:
|:
|:
::
::
::

Вхід:

0

Вихід:

|

Більш тривалі тестові випадки

Подальше читання


Відповіді:


3

Pyth, 64 байти

=QjRTQjCmj\|+:R"[8:]"\.PdedCmm+*\|-h.MZdk*?tk\:\8kdC.[L0h.MZlMQQ

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

Як це працює

=QjRTQ   Converts each number in input to decimal (as a list)
         123 becomes [1,2,3]

----

jCmj\|+:R"[8:]"\.PdedCmm+*\|-h.MZdk*?tk\:\8kdC.[L0h.MZlMQQ

                                              .[L0       Q  0-leftpad each #
                                                  h.MZlMQ   (max length) times

                                             C              transpose

                      mm                    d    for each digit:
                        +                        [convert to] sum of
                         *\|                     "|" repeated
                            -                    the difference of
                             h.MZd               maximum digit in same row
                                  k              and itself.. that many times
                                   *?tk\:\8      and (digit > 1 then ":" or "8") repeated
                                           k     itself many times


the list:
[11,23,52]
->[[1,1],[2,3],[5,2]]
->[[1,2,5],[1,3,2]]
->[["||||8","|||::",":::::"],["||8",":::","|::"]]

                     C      transpose

->[["||||8","||8"],["|||::",":::"],[":::::","|::"]]

  m                          for each number
      +                      [convert to] sum of
                 Pd          every element but the last
       :R"[8:]"\.            with "8" and ":" replaced by "."
                   ed        and the last element
   j\|                       joined with "|"

  C                          transpose
 j                           join (with newlines)

Це відмінна відповідь, крім однієї проблеми. Кінцевий вузол - це не завжди цифра-вісім вузол 8. Насправді це лише 8вузол, коли остання цифра дорівнює 1 (див. Правило 6). Ви конвертуєте всі кінцеві вузли, і це не відповідає специфікації. Також, спробуйте його в Інтернеті! Посилання має інший код від того, який розміщено тут, мабуть
Sherlock9

22

Не читається , 3183 3001 байт

Це було цікавим викликом працювати над, різдвяними святкуваннями, умикатися та вимикатись. Дякую за публікацію! Гольф це було цікаво, тому що специфікація повна винятків та особливих випадків, для яких потрібні великі умови. Крім того , в той час як я не потрібно конвертувати і з десятковою маються на в цей час я так потрібен «Макс» функцію свого роду , щоб визначити найбільшу кількість цифр в кожному номері і найбільше значення цифр в кожному місці.

Перша версія цього становила 4844 байтів, просто для того, щоб дати вам уявлення про те, наскільки я це гольфу.

Програма очікує введення як розділений комою список цілих чисел. Ні пробілів, ні нових рядків. Використання цих даних спричинить невизначеність поведінки.

"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""

Пояснення

Я збираюся ознайомити вас із тим, як працює програма, показуючи, як вона обробляє конкретний вхід 202,100,1.

На початку ми побудуємо кілька значень, які нам знадобляться пізніше - переважно коди ASCII символів, які ми виведемо.

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

Як бачите, '8'і '.'вже доступні. '|'однак це дійсно 124, а не 14. Ми використовуємо цикл while, щоб додати до нього двічі тимчасове значення у слоті №1, щоб отримати 124 (що становить 14 + 55 × 2, оскільки цикл у той час як працює для 56−1 = 55 ітерації). Це економить кілька байтів, оскільки великі цілі букви, такі як 124, дійсно довгі. На наступній схемі я показую розташування кожної змінної, яку використовує програма.

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

Далі ми хочемо ввести всі символи та зберегти їх на стрічці, починаючи з комірки №12 ( p - це запущений покажчик для цього). У той же час ми хочемо знати, наскільки довге найдовше число (скільки цифр). Щоб досягти цього, ми зберігаємо пробіг унітарного руху вліво, починаючи з комірки № −1 (ми використовуємо q як запущений покажчик). Після першого вхідного номера ( 202) стрічка тепер виглядає так:

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

Ви помітили, що числа вимкнено на 4. Ну, коли ми вперше вводимо їх, це їх значення ASCII, тому вони "вимкнено" на 48, а кома - 44. Для кожного символу ми копіюємо 46 з '.'в r, а потім віднімаємо його циклом while (який віднімає 45), а потім додаємо 1. Робимо так, щоб кома (наш роздільник) дорівнювала 0, тому ми можемо використовувати умовне розпізнавання.

Також ви помітили, що ми залишаємо комірку №11 в 0. Нам це потрібно, щоб розпізнати межу першого числа.

Наступним символом буде кома, тому ми зберігаємо 0 в №15, але, звичайно, цього разу ми не просуваємо q . Замість цього ми повертаємо q назад до 0 і починаємо «перезаписувати» 1, які ми вже розмістили.

Після обробки всіх решти символів ми отримуємо це:

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

Як бачимо, значення 1s, написані q, тепер вказують (унарні) довжину найдовшого числа.

Зараз ми використовуємо цикл час для переміщення q вліво, а потім розміщуємо там інший покажчик, який я буду називати r2 . Призначення r2 стане зрозумілим пізніше.

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

На цьому етапі дозвольте мені уточнити термінологію, якою я буду користуватися протягом усього цього.

  • Під числом я маю на увазі одне з вхідних чисел, які розділені комами. У нашому прикладі їх 202, 100 та 1.
  • Під цифрою я маю на увазі одну цифру в конкретному одному з чисел. Перше число має 3 цифри.
  • Під місцем я маю на увазі ті місця, десятки місце, сотні місця і т. Д. Тож якщо я скажу «цифри в поточному місці», а поточне місце - це те місце, ці цифри складають 2, 0 і 1 в цьому замовлення.

Тепер повернемося до нашого звичайного програмування. Весь решта програми - це великий цикл, який рухається q вперед, поки не досягне клітинки № 0. Кожна комірка по дорозі являє собою місце, причому ті розташовуються в крайній правій частині, а q почнеться з найбільш значущої. У нашому прикладі це сотні.

Продовжуємо, збільшуючи точки комірки q на (тобто * q ).

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

Зараз ми перебуваємо на "етапі 2" для сотні. На цьому етапі ми з’ясуємо, яка найбільша цифра серед усіх цифр у сотнях. Для цього ми використовуємо той самий одинарний фокус підрахунку, за винятком цього разу вказівник називається r і покажчик r2 позначає його вихідне положення, до якого нам потрібно скидати його щоразу, коли ми переходимо до наступного числа.

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

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

Не відволікайтеся на те, що q2 вказує на vars. У нас немає пробивки порожньої комірки, тому що ми можемо виявити клітинку № 0 просто тому, що це число нуль.

Далі ми проходимо через поточне число, зменшуючи p і q2 разом, поки * p не дорівнює нулю. У кожному місці значення * q2 вказує нам, що нам потрібно зробити. 1 означає "нічого не робити", тому ми продовжуємо йти. Врешті-решт ми стикаємось із двома у комірці №3. Кожен раз * q2 не дорівнює 1, q2 завжди дорівнює q .

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

Як я вже говорив, етап 2 - це "визначити найбільшу цифру в цьому місці". Таким чином, ми встановлюємо r на r2 , використовуємо цикл час для зменшення * p і переміщаємо r вліво і заповнюємо стрічку 1s, а потім використовуємо інший цикл while, щоб повернути r назад вправо, а інкремент * p знову, щоб відновити значення. Пам’ятайте, що кожен цикл у той час як цикл працює на одну меншу кількість ітерацій, ніж значення, яке ми використовуємо; через це кількість записаних 1с буде на 3 більше (а не на 4 більше), ніж значення цифри, а остаточне значення, збережене в * p, буде ще на 2. Таким чином, це ефективно зменшило * p на 2.

Після цього встановлюємо p на значення p2, а потім робимо все це знову. Вдруге встановіть q2 до 0, знайдіть кінець числа, перемістивши p праворуч, а потім пройдіть цифри цього числа, декрементуючи p і q2 разом. Ще раз ми зустрінемо 2 у комірці №3 і запишемо, що залишилось багато 1s від * r .

У випадку третього числа ми нічого не робимо, тому що у нього немає сотень місця (тому q2 ніколи не досягає q ), але це нормально, оскільки це не впливає на обчислення максимального значення цифри.

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

Також ми встановлюємо комірку * (r - 4) , яку я позначив тут без маркованої стрілки, до 1 (хоча вона вже на 1). Я не збираюся розповідати, чому ще, але, можливо, ви вже здогадалися?

Наступний приріст * q приведе нас до етапу 3, який "віднімає максимальну цифру від усіх цифр у поточному місці". Як і раніше, ми скидаємо p до 11 і q2 до 0, а потім проходимо всі числа так само, як ми це робили на попередньому етапі; за винятком цього часу, * q = 3 замість 2. Кожного разу, коли q2 відповідає q і p знаходиться в сотнях, ми використовуємо цикл час для зменшення * p стільки разів, скільки в блоці зліва * r2 є 1s (5 у нашому прикладі), використовуючи rяк біг вказівник. Ми фактично декрементуємо це ще раз, щоб найбільша цифра закінчилася на −2, з причини, яка стане зрозумілою пізніше:

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

Після того як ми обробили всі числа, ми зараз на кінці етапу 3. Тут ми виконуємо дві особливі речі.

  • Спочатку ми також віднімаємо розмір r -block (плюс 1) від * q , але використовуючи вказівник r2 , який залишає його зліва. * q стає таким негативним. У нашому випадку r -блок має п'ять 1s, тому * q стає −3.
  • По- друге, ми встановлюємо змінну з в нульове значення , щоб вказати , що ми зараз вступаємо вихідний каскад. (Технічно факт, що * q є негативним, вже вказує на вихідний етап, але це занадто складно перевірити, отже, додаткова змінна.)

Тепер ви розумієте, що ми продовжуємо перебирати числа, знаходимо поточне місце (вказане не-1 значенням * q ) у кожному номері, і робимо щось залежно від значення * q . Ми бачимо, що * q спочатку збільшується до 2 (= обчислює максимальне значення цифри), потім 3 (віднімає максимальне значення цифри з кожної цифри в цьому місці), а потім віднімаємо з нього, щоб зробити його від’ємним. Звідти воно продовжуватиметься вгору, поки не досягне 1, тим самим відновивши значення, що означає "нічого не робити". У цей момент ми переходимо до наступного місця.

Тепер, коли * q негативний, ми виводимо. * q - це саме правильне значення, щоб ми вивели потрібну кількість рядків символів до того, як воно досягне 1; якщо найбільша цифра дорівнює 2, нам потрібно вивести 3 ряди. Подивимося, що відбувається при кожному значенні * q :

  • * q = −2:
    • Для першого числа * p - −2, що означає, що нам потрібно вивести a '.'(крапка) або a ':'(двокрапка). Ми вирішуємо, що, дивлячись на q : якщо це −1, ми знаходимося в тому місці, тому виводимо a ':'(який обчислюємо як '8'+2), інакше a '.'.
    • Для другого числа * p дорівнює −3. Все, що не є −2, означає, що ми виводимо '|'(трубу), а потім збільшуємо значення. Таким чином він досягне -2 в потрібному місці, і тоді ми виведемо '.'s / ':'s для решти цієї цифри.
    • У кожному випадку ми також встановлюємо змінну pd до 0, перш ніж обробити число, і встановимо pd (= "надрукований") на ненульове значення, щоб вказати, що ми надрукували символ.
    • Для третього числа жодна обробка не відбувається, оскільки третя цифра не має сотні місць. У цьому випадку pd все одно буде 0 після обробки числа, що вказує на те, що нам все-таки потрібно вивести a '|'(але лише якщо out є не нульовим, оскільки в іншому випадку ми все ще перебуваємо на етапі 2 або 3).
    • Після обробки всіх чисел, якщо з не дорівнює нуль, вихід нового рядка. Зауважте, що нам потрібна змінна зміна, щоб ми не виводили новий рядок на етапі 2 або 3.
  • * q = −1: Те саме, що і раніше, за винятком того, що * p дорівнює 2 для обох перших двох чисел, тому обидва виводять a'.'(і третій виводить a,'|'як і раніше).
  • * q = 0: Коли * q дорівнює 0, це означає «нічого не робити, якщо ми на одному місці, інакше виведіть рядок'|'s незалежно від * p ». Таким чином ми отримуємо прокладку між цифрами.

Тепер ми збільшуємо q, щоб перейти до наступного місця, десятків місця та приросту * q там. На початку 2-го етапу стрічка виглядає так:

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

Потім ми виконуємо Етап 2 так само, як і раніше. Пам'ятайте, що це ефективно віднімає 2 з кожної цифри в цьому місці, а також залишає одинарне число, що залишилося від * r2, що вказує максимальну цифру. Ми залишаємо попередній одинарний номер у спокої і просто продовжуємо продовжувати стрічку вліво; тільки "коштувати" зайвий додатковий код. Коли ми закінчимо, і ми наростимо * q , на початку Етапу 3 стрічка тепер:

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

Власне, це брехня. Згадайте раніше, де я казав, що ми встановили * (r - 4) на 1, і я не сказав вам, чому? Зараз я вам скажу, чому. Це для таких випадків, коли найбільша цифра насправді дорівнює 0, тобто всі цифри в цьому місці дорівнюють 0. Установка * (r - 4) , позначена стрічкою, що не позначається вище, на 1 розширює одинарне число на 1, але лише в цьому окремому випадку. Таким чином ми робимо вигляд, ніби найбільша цифра була 1, а значить, ми виведемо один додатковий рядок.

Після етапу 3 (віднімайте максимальну цифру від усіх цифр у поточному місці), включаючи додатковий крок, який робить * q негативним, стрічка виглядає так. Минулого разу найбільша цифра була представлена ​​−2 у блоці * p , але цього разу вони всі −3, оскільки всі вони насправді нулі, але ми робимо вигляд, ніби максимальна цифра була 1.

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

Тепер давайте подивимося, що відбувається, коли * q просувається до 1:

  • Коли * q = −1, значення p мають усі −3, а значить, ми виводимо '|'s та збільшуємо їх.
  • Коли * q = 0, ми виводимо, '|'тому що це ми завжди робимо, коли * q = 0, незалежно від * p .

Таким чином, отримуємо два ряди труб.

Нарешті, ми переміщуємо * q на своє місце. Це стає цікавим, тому що нам потрібно вивести ':'s, якщо фактична цифра не що інше, а 1, а '8'якщо це 1. Давайте подивимось, як триває програма. По-перше, ми збільшуємо * q, щоб ініціювати Етап 2:

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

Після Етапу 2 ("обчислити максимальне значення цифри") нам залишиться наступне:

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

Після етапу 3 ("віднімайте максимальне значення від усіх цифр у поточному місці") стрічка виглядає так:

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

Тепер по черзі пройдемо кожну ітерацію * q :

  • * q = −2:
    • Перше число: вже при −2, тому виведіть a ':'(а не a, '.'тому що q = −1).
    • Друге число: при −4, тому виведіть a '|'та приріст.
    • Третє число: при −3, тому виведіть a '|'. Однак цього разу, замість збільшення, спрацьовує особливий випадок. Тільки якщо ми виводимо останнє місце ( q = −1), і ми знаходимося в другому останньому рядку для цього ( * q = −2), і цифра насправді є 1 ( * p = −3) , то замість того, щоб збільшити його до −2, встановимо його до −1. Іншими словами, ми використовуємо -1 як особливе значення, щоб вказати, що в наступній ітерації нам потрібно буде вивести '8'замість ':'.
  • * q = −1:
    • Перше число: вже на −2, тому виведіть a ':'.
    • Друге число: при −3, тому виведіть a '|'. Особлива умова не спрацьовує, оскільки * q вже не −2. Тому прирощення.
    • Третє число: при −1, тому виведіть '8'.
  • * q = 0: Зазвичай ми виводимо тут рядок прокладки'|'s, але в спеціальному випадку, коли ми знаходимося в одному місці ( q = −1), ми пропускаємо це.

Після цього q збільшується до 0, а велика в той час як цикл закінчується.

Тепер ви знаєте, як працює такий вхід 202,100,1. Однак є ще один особливий випадок, який ми досі не висвітлювали. Ви можете пам'ятати, що, коли ми обробляли останнє місце, коли * p був −3, ми встановлювали його на −1 для 1(замість того, щоб збільшувати його до −2), щоб наступна ітерація виводила '8'замість цього. Це працює лише тому, що у нас є ітерація, в якій * p дорівнює −3, і ми приймаємо рішення щодо збільшення її чи встановлення до −1. У нас немає такої ітерації, якщо всі цифри в одному місці є 0 або 1. У такому випадку всі значення * p для 1s починаються з −2; немає можливості вирішити встановити його на -1а не збільшувати його від −3 . Через це в Етапі 3 є ще одна спеціальна обсадна оболонка («відняти максимальну цифру від кожної цифри на поточному місці»). Я стверджував, що після вирахування максимального значення цифри з кожної цифри (в якій момент максимальна цифра знаходиться на −1) ми просто ще раз зменшимо її, але насправді існує умова, яка полягає в наступному:

Якщо цифра, яку ми дивимось, дорівнює максимальній цифрі в цьому місці ( * p = −1), і це місце є тим, що розміщується ( q = −1), а максимальна цифра дорівнює 1 ( * (r + 5) = 0, тобто одинарний блок зліва зліва становить лише 5 комірок), тільки тоді залишаємо * p на −1, щоб вказати, що для єдиної ітерації виходу повинно виходити an '8'. У всіх інших випадках ми декрементуємо його ще раз.

Зроблено. Щасливого Нового року!

  • Редагувати 1 (3183 → 3001): кілька новорічних гольфів! Мені вдалося повністю позбутися змінних p2 та r2 ! p тепер перегони вперед і назад, щоб продовжувати знаходити початок і кінець чисел, але, схоже, це коротше в коді. Я також намагався позбутися q2 , але не зміг таким чином скоротити код.

    Я також знайшов ще кілька місць, де я міг застосувати типові нечитані трюки з гольфу, як повторне використання останнього значення циклу. Навести вам приклад замість

    while *(++p) { 1 }         // just increment p until *p is 0; the 1 is a noop
    if (pd) { x } else { y }   // where pd is a variable
    

    Я можу зберегти '""""(зробити перший, потім другий) і '"""(константа 1), записавши його таким чином, як

    if (while *(++p) { pd }) { x } else { y }
    

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


"Нечитабельні", безумовно, влучне ім'я ...
Олексій А.

9
-1 недостатньо пояснень
Хлопець із

7

Javascript (ES6) 750 744 690 604 498 346 245 234 байт

Я новачок у PPCG і подумав, що, можливо, спробую це, подумавши, що це досить просто. Хлопчик, я помилявся !! Я працюю над цим деякий час, і я маю багато займатися гольфом ...
Пропозиції заохочуються! - хоча осмислення цього не буде легким завданням.

Виводить канати, коли вхід є масивом чисел (наприклад:) [204, 1].

a=>(o=m=s="",l=a.map(n=>(s+="|",l=(n+"").length)>m?m=l:l),h=[],a=a.map((n,i)=>[..."0".repeat(m-l[i])+n].map((d,j)=>d<h[j]?d:h[j]=d)),h.map((n,i)=>{i?o+=s+`
`:0;for(j=n;j--;o+=`
`)a.map(d=>o+="|.:8"[d[i]-j<1?0:i<m-1?1:d[i]-1?2:3])}),o)

Пояснення

a=>(

  o=m=s="",                      // m = max number of digits in a number, s = separator string         
  l=a.map(n=>(                   // l = lengths of each number
      s+="|",                    // set the separator string
      l=(n+"").length                 // convert each number to a string
    )>m?m=l:l                    // get max length
  ),
  h=[],
  a=a.map((n,i)=>
    [..."0".repeat(m-l[i])+n]    // add leading 0s to make all same length
    .map((d,j)=>d<h[j]?d:h[j]=d) // set each digit of h to max
  ),

  h.map((n,i)=>{
    i?o+=s+`
`:0;
    for(j=n;j--;o+=`
`)
      a.map(d=>
        o+=
          "|.:8"[
            d[i]-j<1?0
            :i<m-1?1
            :d[i]-1?2:
            3
          ]
      )
  }),
  o
)

Приклад

Введення: Масив чисел: [4,8,15,16,23,42]
Вихід:

|||||.
|||||.
||||..
||....
||||||
|:||||
|:||||
|:|:||
|:::||
::::||
:::::|
::::::
::::::

+1 вражаючий гольф. Чи включите ви приклад із введенням і виходом?
DavidC

@DavidC Дякую! І приклад включений. Викличте його з консолі, і він поверне рядок. :)
квітня

7

Пітон 3, 624 598 595 574 561 535 532 527 525 426 345 328 324 294 288 286 283 280 267 265 255 251 245 238 235 234 230 228 байт

z=input().split();v=max(map(len,z));d=''.join(i.zfill(v)for i in z);x=['']*len(z)
for k,c in enumerate(d):j=k%v;m=int(max(d[j::v]));c=int(c);x[k//v]+="|"*(m-c+0**m+(j>0))+":8."[(c<2)|-(j<v-1)]*c
for r in zip(*x):print(*r,sep='')

Ну, оскільки на це запитання була потрібна відповідь, я надав тут один, де вхідним записом повинен бути розділений пробіл рядків чисел, наприклад "204 1". Хлопчик, чи це довгий. Будь-які пропозиції щодо гольфу (або кращі відповіді) вітаються.

Редагувати: байти, збережені змішуванням вкладок та пробілів.

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

Редагувати: І я врятував ще декілька, включивши останній :8цикл у основний цикл quipu. Тепер якби я міг зрозуміти, чому b=d[j*v+i]==m(d[i::v])не вийде. Зрозумів це, і рішення займає занадто багато байтів. (Також кількість байтів впала, тому що якимось чином вкладки повернулися назад у чотири пробіли. Це, мабуть, форматування блоку коду на цьому сайті)

Редагувати: я реорганізував, як зробив квірус. Тепер він створює по одній нитці за один раз, потім транспонує для друку.

Редагувати: повернув свою відповідь у програму Python 3, щоб зберегти ще кілька байт.

Редагувати: Я знайшов помилку в своєму коді, який зробив це так, що він не надрукував нулі посередині чисел правильно (див. Тестовий випадок 204 1вище). Виправляючи це, мені вдалося пограти в нього :)

Редагувати: я змінив друк, щоб зберегти 10 байт. І я поклав всі старі рахунки байтів назад, просто тому.

Редагувати: Гольф доручив vвикористовувати mapчотири байти. Кредит CarpetPython , як я отримав ідею від їх відповіді тут .

Редагувати: перетворив середину "для циклу всередині циклу", лише одну для циклу на шість байтів.

Редагувати: зараз використовується enumerate. Більше не користуватися l=len(z). Перетворив тернар if-elseу список тринарна. Детальніше дивіться нижче.

Редагувати: Sp3000 запропонував редагувати printта редагувати потрійне умова, яке зберегло кожен байт.

Безголовки:

s = input()
z = s.split()
v = max(map(len, z))                # the amount of digits of the largest number
d = ''.join(i.zfill(v) for i in z)  # pad zeroes until every number is the same length
                                     # then join the numbers into one string
x = ['']*len(z)                     # a list of strings for the output, one for each number

for k,c in enumerate(d):          # for every digit in every number
    i,j = divmod(k, v)            # i is the index of the number we're on
                                   # j is the index of the digit of the number we're on
    m = int(max(d[j::v]))         # the largest of all the digits in the j-th place
    c = int(c)                    # the digit in j-th place of the i-th number
    x[i] += "|"*(m-c+0**m+(j>0))  # pad | to size m-c, until the knots are correctly spaced
                                  # add a | if m<1, all j-th place digits are 0
                                  # add a | if j>0, if it's not at the start, as delimiters
    x[i] += ":8."[(c<2)|-(j<v-1)] * c
    # this is essentially the following code
    # if j<v-1:
    #     x[i] += "."*c      # . knots if not in the units place
    # else:
    #     if c == 1:
    #         x[i] += "8"*c  # 8 knots for ones in the units place
    #     else:
    #         x[i] += ":"*c  # : knots for something else is in the units place

for r in zip(*x):       # transpose so all the rows (the quipu strings) now hang down
    print(*r, sep='')    # join the strings together at each knot
                         # and print each on a separate line

Чи є тут щось специфічне для Python 3 ? Якщо ні, перетворення його на Python 2 могло б заощадити небагато байтів
Cyoce

@Cyoce Нічого занадто специфічного для Python 3. Я щойно почав з Python 3, тому що це версія, яку я маю. Я тестую версію Python 2 на ideone чи щось подібне.
Шерлок9,

@Maltysen Це не працює з входами, які починаються 0, наприклад, з 0 12 4.
Шерлок9,

Ви можете зберегти кілька байт, чергуючи вкладки та пробіли для відступу в Python 2. Я вважаю, що символ 1 вкладки == 8 пробілів відповідно до синтаксичного аналізатора python
Cyoce

for r in zip(*x):print(''.join(r))->print(''.join(r)for r in zip(*x))
Лина монашка

4

C, 238 235 байт

Значно покладаючись на препроцесор C, щоб зробити код якомога коротшим. Як побічний ефект, також робить його значно нечитабельним.

#define l strlen(a[i])
#define d l<k||a[i][l-k]-48
#define m(e) for(i=1;a[i];e<=r?i++:r++);
#define p(e) {m(!putchar(e?'|':k>1?46:d<2?56:58))puts("");}
k,r;main(int i,char**a){m(l)for(k=r,r=1;k;r=k>1){m(d)for(;r;r--)p(d<r)if(--k)p(1)}}

У Ubuntu 14.04 ви можете скласти код прямолінійно gcc quipu.c(будь ласка, ігноруйте попередження). Приклад запуску виконуваного файлу:

$ ./a.out 1 2 3 2 1
||:||
|:::|
8:::8

Перевірено на всіх тестових випадках ОП.

Не вихідний код:

// Standard library; leaving out the includes still gives executable code despite the warnings.
#include <stdio.h>
#include <string.h>

// 4 preprocessor macros.
// Note: some of these actually make use of the fact that parentheses have been left out

// l: length of argument i
#define l     strlen(a[i])

// d: shorthand for a digit
#define d     l<k || a[i][l-k]-'0'

// m: loop across all arguments; calculates r as the maximum of expression e
#define m(e)  for (i=1; a[i]; e<=r ? i++ : r++);

// p: prints one line of output
// note: intentionally does not use the r++ code branch of m;
//       putchar always returns a non-zero number here, so !putchar is zero,
//       which is always <=r (because r is never negative)
// note: the semicolon after m(...) is redundant;
//       the definition of m already contains a semicolon
// note: puts("") outputs a newline
#define p(e)  { m(!putchar(e ? '|' : k > 1 ? '.' : d < 2 ? '8' : ':')); puts(""); }

// k: knot position; 1 for units, 2 for tens, 3 for hundreds...
int k;

// r: input and output value for m
// note: the first time we call m, we need r to be zero;
//       by defining it outside main, it is automatically initialized as such
int r;

// function main
// note: parameter i (normally named argc by convention) is not needed
//       (the last element of argv is known; it is followed by a NULL pointer)
//       but we cannot leave it out (otherwise we cannot access argv)
//       so it serves as a local variable (to loop through arguments; see m)
// note: parameter a (normally named argv by convention)
//       is the array of arguments (starting from index 1)
int main(int i, char **a)
{
    // Determine the longest argument; store its length in r.
    // This is the number of knot positions to consider.
    m(l)

    // Iterate k through the knot positions from top to bottom.
    // Note: k > 0 has been abbreviated to k.
    // Note: for each iteration, we also initialize r with either 0 or 1.
    //       0 = suppress printing when all knots are zero
    //       1 = always print, even when all knots are zero
    for (k = r, r = 1; k > 0; r = k > 1)
    {
        // Determine the highest digit at this knot position.
        // Note: due to the absence of parentheses, d mixes up with <=r into:
        // (l < k) || (a[i][l-k]-'0' <= r)
        m(d)

        // Count the digits down.
        for (; r; r--)
        {
            // Print a single line of output.
            // When d (the digit in the current strand) is less than the counter,
            // then print a '|', otherwise print a knot.
            p(d < r)
        }

        // Decrement k (go to next knot position).
        // If this was not the last iteration...
        if (--k > 0)
        {
            // Print separator line.
            p(1)
        }
    }

    // Return exit code zero; redundant.
    return 0;
}

Вітаємо! Як найкоротша відповідь, розміщена протягом періоду щедрості, ви отримали мою нагороду в розмірі +50 представників. Гарна відповідь! :)
Олексій А.

4

Mathematica 436 453 357 352 347 байт

t=Transpose;y=ConstantArray;a=Table;
g@j_:=(s=t[PadLeft[#,Max[Length/@i]]&/@(i=IntegerDigits@#)]&;p_~u~o_:=(m=Max@p;c=If[o==-2,":","."];w=If[o==-2,"8","."];p//.{0->a["|",Max@{1,m}],1->Join[a["|",{m-1}],{w}],n_/;MemberQ[2~Range~9,n]:>Join[y["|",m-n ],c~y~n]});t[Join@@@t@Join[u[#,0]&/@Most@#,u[#,-2]&/@{#[[-1]]}]]&[Riffle[(s@j),{a[0,Length@j]}]]//Grid)

Вище

  • Розбиває кожне ціле число до списку цифр, використовуючи IntegerDigits; прокладіть кожне число з нулями зліва (щоб забезпечити рівний інтервал); кожному вхідному номеру, тепер розкладеному на цифри, відповідає рядок масиву; кожен стовпець представляє значення місця. Масив переміщується.
  • Замінює цифри списком вузлів набиванням. Для підрозділів використовується дещо інша рутина відповідності шаблону.

Приклад

g[Range[0, 50]]

п’ятдесят


Transpose@Join? Це повинно бути, правда?
CalculatorFeline

Так. Дякуємо, що це зробили.
DavidC

Простір прямо перед цим.
CalculatorFeline

1

R - 446 444

Я бачу, що поки що немає рішення R, тому ось одне. Функція приймає вектор з цілими числами.

function(x){r=nchar(max(x));c=length(x);m=matrix(0,r,c);for(i in 1:c){t=as.numeric(strsplit(as.character(x[i]),"")[[1]]);m[(r+1-length(t)):r,i]=t};Q=c();for(i in 1:r){d=m[i,];z=ifelse(max(d)>0,max(d),1);q=matrix("|",z,c);for(j in 1:c){v=m[i,j];if(i==r){if(v==1)q[z,j]=8;if(v>1)q[(z-v+1):z,j]=rep(":",v)};if(i<r){if(v>0)q[(z-v+1):z,j]=rep(".",v)}};if(i!=1&sum(d)>0)q=rbind(rep("|",c),q);Q=rbind(Q,q)};for(i in 1:nrow(Q))cat(Q[i,],sep="",fill=T)}

Безумовно

# Some test data
test <- c(201, 0, 100, 222, 53)

# Define function
quipu <- function (x) {

    # Create matrix with a row for each digit and a column for each number
    r=nchar(max(x));c=length(x);m <- matrix(0,r,c)
    for(i in 1:c) {
        t=as.numeric(strsplit(as.character(x[i]),"")[[1]])
        m[(r+1-length(t)):r,i]=t
    }

    # Loop through each row (digit) starting at the top of the quipu
    Q=c() # Empty matrix to store quipu 
    for(i in 1:r){

        d=m[i,]
        z=ifelse(max(d)>0,max(d),1)
        q=matrix("|",z,c)

        # Loop through each column (number in the vector) starting at the leftmost quipu
        for(j in 1:c){

            # The digit
            v=m[i,j]

            # If it is the last segment of the quipu
            if(i==r){
                if(v==1){q[z,j]=8} # If unit digit =1
                if(v>1){q[(z-v+1):z,j]=rep(":",v)} # If unit digit >1               
            }

            # If it is not the last segment of the quipu
            if(i<r){
                if(v>0){q[(z-v+1):z,j]=rep(".",v)} # If non-unit digit >0   
            }
        }

        # Add segment to Q
        if(i!=1 & sum(d)>0){q=rbind(rep("|",c),q)}
        Q=rbind(Q,q)    
    }

    # Print quipu
    for(i in 1:nrow(Q)) {cat(Q[i,], sep="", fill=T)}
}

# Test
quipu(test)

Вам потрібно if(v>0)в своєму if(i<r)пункті? Чи приймає R діапазон, як z+1:zколи v==0? Якби це q[z+1:z,j]взагалі не вплинуло, я б подумав. Також R має elseключове слово та якесь else ifключове слово? Якщо так, ви зможете покататись на деяких цих умовах.
Шерлок9

if(v>0)потрібен, тому що якщо v=0індекс не виходить за межі (тобто намагається отримати нульовий рядок + 1). R є else, і я насправді спробував вашу пропозицію і використовував elseтам, де це можливо, але виявилося однакову кількість байтів.
Повільний лоріс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.