Ваги для журналів призначені для Quitters


24

Всім відомо, що шкали журналів призначені для квітерів . Отже, ви повинні написати програму або функцію, яка дефітифікує гістограму зі шкалою журналу, заданою базою.

Введення смугової графіки приймається як один рядок, який представляє собою список барів, де кожен рядок смугової діаграми масштабу журналу розділений розділювачем для друку (або пробілом) на ваш вибір (так 0x09-0x0A + 0x20-0x7E) та складається із символу наповнювача, який не вибирається для друку (так 0x21-0x7E) на ваш вибір.

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

Приклад

Вибираємо роздільник "\ n" (один новий рядок) та символ заповнення "#". Вхід, що передається нашій програмі або функції:

base = 2 і string =

####
##
######
###

Код визначить, що довжини брусків є [4,2,6,3]. Було б обчислено анти-журнал кожної довжини з базою, 2щоб отримати [2^4,2^2,2^6,2^3]= [16,4,64,8]. Потім довжини виводяться у форматі лінійної шкали:

################
####
################################################################
########

Введення-виведення

Ваша програма чи функція можуть вводити та виводити в будь-якому розумному форматі .

Гарантована база буде на ціле число більше 1. Ви можете припустити, що база менша за 256. Введений рядок гарантовано повністю відповідає регулярному вираженню (f+s)+f+, де fі sзамінюється відповідно вашим наповнювачем та роздільником.

Вихідна рядок повинні повністю відповідати регулярному виразу (f+s)+f+, де fі sзамінюються з тим же наповнювачем і роздільником відповідно. Необов'язково вихід може мати зворотний новий рядок.

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

Тестові шафи

(припустимо, наповнювач є, #а роздільник є \n)

base
-
input string
-
output string
-----
2
-
####
##
######
###
-
################
####
################################################################
########
-----
3
-
##
#
###
#
-
#########
###
###########################
###
-----
100
-
#   I am not the delimiter
###  nor the filler
-
Anything (You do not have to handle input which does not match the regex)
-----
1
-
###
#######
###################################################
- 
Anything (You do not have to handle bases less than or equal to 1).
-----
5
-
####
##
###
#
-
#################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################    
#########################
#############################################################################################################################
#####
-----
2
-
#
#
##
##
#
##
#
#
#
#
##
##
#
#
##
#
-
##
##
####
####
##
####
##
##
##
##
####
####
##
##
####
##

Відповіді:


6

32-бітна функція машинного коду x86, 21 байт

Функція машинного коду x86-64, 22 байти

Збереження 1B в 32-бітному режимі вимагає використання роздільника = filler-1, наприклад, fill=0і sep=/. У 22-байтовій версії можна використовувати довільний вибір сепаратора та наповнювача.


Це 21-байтова версія з входом-роздільником = \n(0xa), вихід-наповнювач = 0, вихід-роздільник = /= наповнювач-1. Ці константи можна легко змінити.

; see the source for more comments
; RDI points to the output buffer,  RSI points to the src string
; EDX holds the base
; This is the 32-bit version.
; The 64-bit version is the same, but the DEC is one byte longer (or we can just mov al,output_separator)
08048080 <str_exp>:
 8048080:       6a 01           push   0x1
 8048082:       59              pop    ecx           ; ecx = 1 = base**0
 8048083:       ac                      lods   al,BYTE PTR ds:[esi]  ; skip the first char so we don't do too many multiplies

; read an input row and accumulate base**n as we go.
08048084 <str_exp.read_bar>:
 8048084:       0f af ca        imul   ecx,edx       ; accumulate the exponential
 8048087:       ac              lods   al,BYTE PTR ds:[esi]
 8048088:       3c 0a           cmp    al,0xa        ; input_separator = newline
 804808a:       77 f8           ja     8048084 <str_exp.read_bar>
 ; AL = separator or terminator
 ; flags = below (CF=1) or equal (ZF=1).  Equal also implies CF=0 in this case.

 ; store the output row
 804808c:       b0 30           mov    al,0x30       ; output_filler
 804808e:       f3 aa           rep stos BYTE PTR es:[edi],al  ; ecx bytes of filler
 8048090:       48              dec    eax           ; mov al,output_separator 
 8048091:       aa              stos   BYTE PTR es:[edi],al  ;append delim

 ; CF still set from the inner loop, even after DEC clobbers the other flags
 8048092:       73 ec           jnc    8048080 <str_exp>  ; new row if this is a separator, not terminator

 8048094:       c3              ret    

08048095  <end_of_function>
; 0x95 - 0x80 = 0x15 = 21 bytes

64-бітна версія на 1 байт довша, використовуючи 2-байтний DEC або a mov al, output_separator. Крім цього, машинний код однаковий для обох версій, але деякі назви регістрів змінюються (наприклад, rcxзамість ecxв pop).

Вибірка вибору з запуску програми тестування (база 3):

$ ./string-exponential $'.\n..\n...\n....' $(seq 3);echo 
000/000000000/000000000000000000000000000/000000000000000000000000000000000000000000000000000000000000000000000000000000000/

Алгоритм :

Проведіть петлю над введенням, роблячи exp *= baseдля кожного заповнювача. На роздільниках та кінцевому нульовому байті додайте expбайти наповнювача, а потім роздільник до вихідного рядка та скиньте на exp=1. Дуже зручно, що вхід гарантовано не закінчується як новою лінією, так і термінатором.

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


Правила дозволяють розділяти кінцевий роздільник лише тоді, коли це останній новий рядок. Моя реалізація завжди додає роздільник. Щоб отримати збереження 1B в 32-бітному режимі, для цього правила потрібен роздільник = 0xa ( '\n'ASCII LF = linefeed), наповнювач = 0xb ( '\v'ASCII VT = вертикальна вкладка). Це не дуже зручно для людини, але задовольняє букву закону. (Ви можете hexdump або
tr $'\v' xвисновок, щоб переконатися, що він працює, або змінити константу, щоб розділювач виводу і наповнювач були надруковані. Я також помітив, що правила, схоже, вимагають, щоб він міг приймати вхід з тим же заповненням / sep, який він використовує для виведення , але я не бачу нічого корисного від порушення цього правила.).


Джерело NASM / YASM Створіть як 32 або 64-бітний код, використовуючи %ifматеріали, що входять до програми тестування, або просто змініть rcx на ecx.

input_separator equ 0xa  ; `\n` in NASM syntax, but YASM doesn't do C-style escapes

output_filler equ '0'                 ; For strict rules-compliance, needs to be input_separator+1
output_separator equ output_filler-1  ; saves 1B in 32-bit vs. an arbitrary choice
    ;; Using output_filler+1 is also possible, but isn't compatible with using the same filler and separator for input and output.

global str_exp
str_exp:                        ; void str_exp(char *out /*rdi*/, const char *src /*rsi*/,
                                ;              unsigned base /*edx*/);
.new_row:
    push   1
    pop    rcx                  ; ecx=1 = base**0

    lodsb                       ; Skip the first char, since we multiply for the separator
.read_bar:
    imul   ecx, edx             ; accumulate the exponential
    lodsb
    cmp    al, input_separator
    ja .read_bar                ; anything > separator is treated as filler
    ; AL = separator or terminator
    ; flags = below (CF=1) or equal (ZF=1).  Equal also implies CF=0, since x-x doesn't produce carry.

    mov    al, output_filler
    rep stosb                   ; append ecx bytes of filler to the output string
%if output_separator == output_filler-1
    dec   eax         ; saves 1B in the 32-bit version.  Use dec even in 64-bit for easier testing
%else
    mov    al, output_separator
%endif
    stosb                       ; append the delimiter

    ; CF is still set from the .read_bar loop, even if DEC clobbered the other flags
    ; JNC/JNB here is equivalent to JE on the original flags, because we can only be here if the char was below-or-equal the separator
    jnc .new_row            ; separator means more rows, else it's a terminator
    ; (f+s)+f+ full-match guarantees that the input doesn't end with separator + terminator
    ret

Функція слідує за системою x86-64 SystemV ABI, з підписом.
void str_exp(char *out /*rdi*/, const char *src /*rsi*/, unsigned base /*edx*/);

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

xchg eax,ediПовернення кінцевого вказівника в eax або rax коштуватиме 1 або 2 байти ( ). (Якщо використовується x32 ABI, покажчики гарантовано становлять лише 32 біти, інакше ми повинні використовуватись xchg rax,rdiу випадку, якщо абонент передає вказівник до буфера поза низькими 32 бітами.) Я не включив це у версію I публікація, оскільки є обхідні шляхи rdi, що може викликати абонент, не отримуючи значення , тому ви можете зателефонувати цьому з C без обгортки.

Ми навіть не скасовуємо нульовий рядок або щось подібне, тому це лише новий рядок. Для виправлення цього знадобиться 2 байти: xchg eax,ecx / stosb (rcx дорівнює нулю від rep stosb.)

Способи з'ясувати довжину вихідного рядка:

  • rdi вказує на один-останній-кінець рядка при поверненні (тому абонент може зробити len = end-start)
  • абонент може просто знати, скільки рядків було на вході, і рахувати нові рядки
  • абонент може використовувати великий нульовий буфер і strlen()потім.

Вони не дуже чи ефективні (за винятком використання зворотного значення RDI від абонента asm), але якщо ви цього хочете, тоді не викликайте функцій asm з гольфу від C.: P


Обмеження розміру / діапазону

Максимальний розмір вихідного рядка обмежений лише обмеженнями адресного простору віртуальної пам'яті. (Головним чином, поточне обладнання x86-64 підтримує лише 48 значущих бітів у віртуальних адресах, розділених навпіл, оскільки вони підписують-розширюють замість нульового розширення. Див. Схему у зв’язаній відповіді .)

Кожен рядок може містити максимум 2 ** 32 - 1 байта наповнювача, оскільки я накопичую експоненцію в 32-бітному регістрі.

Функція працює правильно для баз від 0 до 2 ** 32 - 1. (Правильно для бази 0 0 0 x x = 0, тобто просто порожні рядки без байтів заповнення. Правильне для бази 1 - 1 ^ x = 1, тому завжди 1 наповнювач на рядок.)

Це також надзвичайно швидко в Intel IvyBridge і пізніше, особливо для великих рядків, записаних у вирівняну пам'ять. rep stosbє оптимальною реалізацією memset()для великих рахунків з вирівнюваними покажчиками на процесорах з функцією ERMSB . наприклад, 180 ** 4 становить 0,97 Гб, і на моєму i7-6700k Skylake (з ~ 256 кб м'яких сторінок-помилок) потрібно 0,27 секунди, щоб записати на / dev / null. (У Linux драйвер пристрою для / dev / null нікуди не копіює дані, він просто повертається. Отже, весь час знаходиться у rep stosbта м'яких сторінках-помилках, які спрацьовують при першому дотику до пам'яті. Це на жаль, не використовувати прозорі величезні сторінки для масиву в BSS. Можливо, madvise()системний виклик прискорить його.)

Тестова програма :

Побудуйте статичну двійкову і запустіть як ./string-exponential $'#\n##\n###' $(seq 2)для базової 2. Щоб уникнути впровадження програми atoi, вона використовує base = argc-2. (Обмеження довжини командного рядка запобігають тестуванню смішно великих баз.)

Ця обгортка працює для вихідних рядків до 1 ГБ. (Це робить лише єдиний системний виклик write () навіть для гігантських рядків, але Linux підтримує це навіть для запису на труби). Для підрахунку символів або перейдіть до нього, wc -cабо використайте, strace ./foo ... > /dev/nullщоб побачити аргумент до системного виклику запису.

Для цього використовується корисне значення RDI для обчислення довжини рядка як аргументу write().

;;; Test program that calls it
;;; Assembles correctly for either x86-64 or i386, using the following %if stuff.
;;; This block of macro-stuff also lets us build the function itself as 32 or 64-bit with no source changes.

%ifidn __OUTPUT_FORMAT__, elf64
%define CPUMODE 64
%define STACKWIDTH 8    ; push / pop 8 bytes
%define PTRWIDTH 8
%elifidn __OUTPUT_FORMAT__, elfx32
%define CPUMODE 64
%define STACKWIDTH 8    ; push / pop 8 bytes
%define PTRWIDTH 4
%else
%define CPUMODE 32
%define STACKWIDTH 4    ; push / pop 4 bytes
%define PTRWIDTH 4
%define rcx ecx      ; Use the 32-bit names everywhere, even in addressing modes and push/pop, for 32-bit code
%define rsi esi
%define rdi edi
%define rsp esp
%endif


global _start
_start:
    mov  rsi, [rsp+PTRWIDTH + PTRWIDTH*1]  ; rsi = argv[1]
    mov  edx, [rsp]          ; base = argc
    sub  edx, 2              ; base = argc-2  (so it's possible to test base=0 and base=1, and so ./foo $'xxx\nxx\nx' $(seq 2) has the actual base in the arg to seq)
    mov  edi, outbuf         ; output buffer.  static data is in the low 2G of address space, so 32-bit mov is fine.  This part isn't golfed, though

    call str_exp             ; str_exp(outbuf, argv[1], argc-2)
    ;  leaves RDI pointing to one-past-the-end of the string
    mov  esi, outbuf

    mov  edx, edi
    sub  edx, esi               ; length = end - start

%if CPUMODE == 64 ; use the x86-64 ABI
    mov  edi, 1                 ; fd=1 (stdout)
    mov  eax, 1                 ; SYS_write  (Linux x86-64 ABI, from /usr/include/asm/unistd_64.h)
    syscall                     ; write(1, outbuf, length);

    xor edi,edi
    mov eax,231   ; exit_group(0)
    syscall


%else  ; Use the i386 32-bit ABI (with legacy int 0x80 instead of sysenter for convenience)
    mov ebx, 1
    mov eax, 4                  ; SYS_write (Linux i386 ABI, from /usr/include/asm/unistd_32.h)
    mov ecx, esi  ; outbuf
    ; 3rd arg goes in edx for both ABIs, conveniently enough
    int 0x80                    ; write(1, outbuf, length)

    xor ebx,ebx
    mov eax, 1
    int 0x80     ; 32-bit ABI _exit(0)
%endif


section .bss
align 2*1024*1024 ; hugepage alignment (32-bit uses 4M hugepages, but whatever)
outbuf:    resb 1024*1024*1024 * 1
; 2GB of code+data is the limit for the default 64-bit code model.
; But with -m32, a 2GB bss doesn't get mapped, so we segfault.  1GB is plenty anyway.

Це було цікавим викликом, який дуже добре піддався підсилення, особливо x86 string ops . Правила добре розроблені, щоб уникнути необхідності обробляти новий рядок і потім термінатор в кінці вхідного рядка.

Експоненція з повторним множенням подібна до множення з повторним додаванням, і мені потрібно було циклічно рахувати символи у кожному вхідному рядку.

Я розглядав можливість використання одного операнда mulабо imulзамість більш тривалого imul r,r, але його неявне використання EAX суперечить LODSB.


Я також спробував SCASB замість завантаження та порівняння , але мені було потрібно xchg esi,ediдо і після внутрішнього циклу, оскільки SCASB і STOSB обидва використовують EDI. (Отже, 64-розрядна версія повинна використовувати x32 ABI, щоб уникнути обрізання 64-бітних покажчиків).

Уникати STOSB - це не варіант; нічого іншого немає ніде поруч, як короткий. І половина переваги використання SCASB полягає в тому, що AL = наповнювач після виходу з внутрішнього циклу, тому нам не потрібні настройки для REP STOSB.

SCASB порівнює в іншому напрямку з тим, що я робив, тому мені потрібно було змінити порівняння.

Моя найкраща спроба з xchg та scasb. Працює, але не коротше. ( 32-розрядний код, використовуючи inc/ decтрюк, щоб змінити наповнювач на роздільник ).

; SCASB version, 24 bytes.  Also experimenting with a different loop structure for the inner loop, but all these ideas are break-even at best
; Using separator = filler+1 instead of filler-1 was necessary to distinguish separator from terminator from just CF.

input_filler equ '.'    ; bytes below this -> terminator.  Bytes above this -> separator
output_filler equ input_filler       ; implicit
output_separator equ input_filler+1  ; ('/') implicit

 8048080:       89 d1                   mov    ecx,edx    ; ecx=base**1
 8048082:       b0 2e                   mov    al,0x2e    ; input_filler= .
 8048084:       87 fe                   xchg   esi,edi
 8048086:       ae                      scas   al,BYTE PTR es:[edi]

08048087 <str_exp.read_bar>:
 8048087:       ae                      scas   al,BYTE PTR es:[edi]
 8048088:       75 05                   jne    804808f <str_exp.bar_end>
 804808a:       0f af ca                imul   ecx,edx           ; exit the loop before multiplying for non-filler
 804808d:       eb f8                   jmp    8048087 <str_exp.read_bar>   ; The other loop structure (ending with the conditional) would work with SCASB, too.  Just showing this for variety.
0804808f <str_exp.bar_end>:

; flags = below if CF=1 (filler<separator),  above if CF=0 (filler<terminator)
; (CF=0 is the AE condition, but we can't be here on equal)
; So CF is enough info to distinguish separator from terminator if we clobber ZF with INC

; AL = input_filler = output_filler
 804808f:       87 fe                   xchg   esi,edi
 8048091:       f3 aa                   rep stos BYTE PTR es:[edi],al
 8048093:       40                      inc    eax         ; output_separator
 8048094:       aa                      stos   BYTE PTR es:[edi],al
 8048095:       72 e9                   jc     8048080 <str_exp>   ; CF is still set from the inner loop
 8048097:       c3                      ret    

Для введення ../.../., виробляє ..../......../../. Я не збираюся турбуватися, показуючи hexdump версії з роздільником = newline.


4

Mathematica 41 38 байт

-3 байти завдяки LLlAMnYP

Це сприймає введення як список рядків, за яким слідує ціле число. Вихід - це також список рядків.

""<>"#"~Table~#&/@(#2^StringLength@#)&

Пояснення:

                   StringLength@# & - find length of each string in first input
                   #2^               & - raise to power of second input
                /@(                 )  - Uses each of these numbers on an inner function of ...
    "#"~Table~#&                       - Create arrys of specific length using character "#"
 ""<>                                  - Join arrays of characters together to make strings

Стара версія, 41 байт

"#"~StringRepeat~#&/@(#2^StringLength@#)&

"" <> "#"~Table~#на 3 байти коротше, що "#"~StringRepeat~#, ймовірно, також можна зіграти.
LLlAMnYP

3

Japt , 7 байт

Приймає графік як масив рядків з "як заповнювач, а основу - як ціле число.

£QpVpXl

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

Додайте }Rдо кінця, щоб замість цього граф взяти рядок, відокремлений новим рядком. ( Спробуйте )


Пояснення

    :Implicit input of array U.
£   :Map over the array, replacing each element with ...
Q   :the " character ...
p   :repeated ...
V   :integer input ...
p   :to the power of ...
Xl  :the length of the current element times.
    :Implicit output of result.

3

MATL , 14 11 байт

Y'iw^1HL(Y"

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

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

Пояснення

       % Implicit input: string
       %   STACK: '## # ### #'
Y'     % Run-length encoding
       %   STACK: '# # # #', [2 1 1 1 3 1 1]
i      % Input: number
       %   STACK: '# # # #', [2 1 1 1 3 1 1], 3
w      % Swap
       %   STACK: '# # # #', 3, [2 1 1 1 3 1 1]
^      % Power, element-wise
       %   STACK: '# # # #', [9 3 3 3 9 3 3]
1      % Push 1
       %   STACK: '# # # #', [9 3 3 3 27 3 3], 1
HL     % Push [2 2 1j]. When used as an index, this means 2:2:end
       %   STACK: '# # # #', [9 3 3 3 27 3 3], 1, [2 2 1j]
(      % Write specified value at specified entries
       %   STACK: '# # # #', [9 1 3 1 27 1 3]
Y"     % Run-length decoding
       %  STACK: '######### ### ########################### ###'
       % Implicit display

Це, здається, не працює; довжина кожного рядка у висновку для тестового випадку, який ви включили до свого TIO, має становити 9,3,27,9, але замість цього становить 6,3,9,3.
Кудлатий

@Shaggy Ви абсолютно праві. Дякуємо, що помітили. Я помилився в останній редакції. Я повернувся до попередньої версії, це правильно
Луїс Мендо

Не вдалося зрозуміти, як це працює з пояснення - тоді я перейшов до ТІО! : D
Кудлатий

1
@Shaggy Я щойно додав пояснення до цієї версії, сподіваюсь, ясніше!
Луїс Мендо

3

Haskell , 37 33 байт

4 байти поголилися завдяки sudee

\b->map(\x->'#'<$[1..b^length x])

Опис:

\b->                               -- take an integer b as the first input input
    map(\x->                    )  -- apply the following to every element x in the second input
            '#'<$[1..b^length x]   ---- replicate '#' (b^(length x)) times

Розчаровуючи, це на 2 байти набагато коротше, ніж у важкій для читання версії pointfree:

map.(flip replicate '#'.).(.length).(^)

Вхід повинен бути одним рядком
bartavelle

@bartavelle, не обов'язково.
Кудлатий

Це те, що я розумію під введенням гістограми, приймається як один рядок ...
bartavelle

1
@bartavelle: Вихід і введення також можуть бути списком рядків, а не обмеженим підрядком, хоча повинно бути можливість зрозуміти, яка панель є.
Джуліан Вольф

2
Ви можете замінити replicate(b^length x)'#'на '#'<$[1..b^length x].
sudee

3

ReRegex , 105 байт

#import math
(\d+)\n((;.*\n)*)(_+)/$1\n$2;$1^d<$4>/^\d+\n((;\d+\n?)+)$/$1/^((_*\n)*);(\d+)/$1u<$3>/#input

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

ReRegex - це як некрасивий двоюрідний брат Retina, який докладає всіх зусиль для регулярних виразів, замість того, щоб мати власних фантазійних операторів.

Звичайно, це теж є #import і #inputзберегти як введення жорсткого кодування, так і переписувати одні і ті ж вирази знову і знову.

Пояснив.

Вводиться у вигляді:

2
____
__
______
___

на STDIN і дає вихід подібний

________________
____
________________________________________________________________
________

По-перше, програма імпортує бібліотеку Math , яка, звичайно, повністю написана в ReRegex. Основна частина цього становить три регулярні вирази.

(\d+)\n((;.*\n)*)(_+)   ->  $1\n$2;$1^d<$4>
^\d+\n((;\d+\n?)+)$     ->  $1
^((_*\n)*);(\d+)        ->  $1u<$3>

Перший відповідає нашій вхідній базі і шукає рядок одинарного після нього. він потім замінює цей рядок на;$1^d<$4> , який є базовим, на потужність (У десятковій) Унарності. Бібліотека Math обробляє базову конверсію та показник. A; ставиться на початок, щоб визначити його пізніше як закінчений.

Другий, збігається з базовою, потім безліччю рядків; перед закінченням. Якщо це відповідає всій справі, вона відривається від бази. залишаючи uf лише відповіді та ;s.

Останнє, відповідає лише одинаковому на старті, необов'язково, потім ;відповідь. Потім вона перетворює цю відповідь в одинарну знову, без ;.

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



2

Рода , 19 байт

f n,s{s|["#"*n^#_]}

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

Приймає масив як вхідний і повертає потік значень як вихід.

Пояснення

f n,s{s|["#"*n^#_]}              n is the number and s is the array of strings consisting of #s
      s|                         Push the each value of s to the stream
        [        ]               For each push
         "#"*                     "#" repeated
             n^#_                 n raised to the length of the string

2

Haskell , 32 байти

f b=map$foldr(\_->([1..b]>>))"#"

Спробуйте в Інтернеті! Приклад використання: f 3 ["##","#","###","#"]повертає ["#########","###","###########################","###"].

Використовуйте mapM putStrLn $ f 3 ["##","#","###","#"]для отримання більш візуального виходу:

#########
###
###########################
###

Просто коментуючи тут, бо я не можу коментувати публікацію, яку ви видалили ... спробуйте sum[sum[]^sum[],sum[]^sum[]].
Ørjan Johansen

2

05AB1E , 9 байт

Штрихи розділені пробілами, вихідний символ такий же, як і вхідний символ.

¬Š#€gm×ðý

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

¬Š#€gm×ðý   Arguments: n, s
¬           Head, get bar character
 Š          Rearrange stack to get: s, n, bar-character
  #         Split s on spaces
   €g       Map to length
     m      n to that power
      ×     That many bar-characters
       ðý   Join on space
            Implicit output

1

PHP, 69 байт

<?foreach($_GET[1]as$l)echo str_pad("",$_GET[0]**strlen($l),"#")."
";

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


Це повертається з провідним новим рядком, що заборонено регулярним виразом. Ви можете використовувати [str_pad]."\n"замість цього, "\n".[str_pad]щоб виправити це (+1 байт). Крім того, ви можете припустити, що таке наповнювач, так що ви можете зберегти два байти $l[0], змінивши його на "#".
fireflame241

@ fireflame241 Здійснено Дякую
Йорг Гюльсерманн

1

Желе , 7 байт

ṁL*@¥¥€

Монадичне посилання, що приймає та повертає списки барів (самі списки символів, рядки AKA), характер заповнення є гнучким.

Спробуйте в Інтернеті! (нижній колонтитул вподобає отриманий список, з'єднуючи його елементи з новими рядками.)

Як?

ṁL*@¥¥€ - Main link: list of list of characters, bars; number, base
     ¥€ - last two links as a dyad for €ach bar in bars:
    ¥   -   last two links as a dyad:
 L      -     length (of a bar)
  *@    -     exponentiate (swap @rguments) (base ^ length)
ṁ       -   mould like (e.g. moulding "##" like 8 yields "########")

Альтернативно 7-байтовий: ṁ"L€*@¥- отримати довжину кожного штриха ( L€), підняти baseдо цієї потужності ( *@), потім zip ( ") список і те, що застосує moldd dyad ( ) між ними.


4 квітки та 3 фактичні посилання? Ця проблема є досить важкою для контролю над потоком даних ...
ETHproductions

Так, може бути доступне коротше рішення ...
Джонатан Аллан

@JonathanAllan Боюся, що немає.
Ерік Аутгольфер

@ETHproductions Це насправді одна ланка в цілому. Пояснення могло бути майже одним рядком.
Ерік Аутгольфер

1

Рубін , 29 байт

->x,y{x.map{|z|?#*y**z.size}}

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

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


1
?XОператор, де Xє будь то символ, є «отримати уявлення за замовчуванням цього символу» оператор. У Ruby <1.9 він би повернув точку коду Unicode символу, тому що так було визначено символи, але тепер він повертає рядок, що містить символ. Це частина загального переходу до більш послідовної обробки Unicode в Ruby.
Тутлеман

@Turtleman, чи є істерична родзинка, для чого ?Xїї використовують? Багато звичаїв Рубі, як і безліч $змінних, існує через знайомство з Perl.
ymbirtt

1

JavaScript (ES8), 39 байт

База приймає як ціле число, а графік - масив рядків з будь-яким символом як наповнювач, використовуючи синтаксис currying.

b=>a=>a.map(x=>x.padEnd(b**x.length,x))

Спробуй це

f=
b=>a=>a.map(x=>x.padEnd(b**x.length,x))
oninput=_=>o.innerText=f(i.value)(j.value.split`\n`).join`\n`
o.innerText=f(i.value=2)((j.value=`####\n##\n######\n###`).split`\n`).join`\n`
*{box-sizing:border-box}#i,#j{margin:0 0 5px;width:200px}#j{display:block;height:100px
<input id=i type=number><textarea id=j></textarea><pre id=o>


Альтернативно, 49 байт

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

b=>s=>s.replace(/.+/g,m=>m.padEnd(b**m.length,m))

Не думаю, що вам потрібен mпрапор на регулярному виразі, за замовчуванням .не відповідає новим рядкам.
ETHproductions

Гм, не знаю, звідки це взялося - небезпека спроби гольфу з телефону. Дякуємо, що вказали на це, @ETHproductions.
Кудлатий

0

Математика, 86 байт

(s=#2^StringLength[StringSplit@#1];StringJoin/@Table[Table["#",s[[i]]],{i,Length@s}])&

вхід

["#### \ n ## \ n ###### \ n ###", 2]


нормально ... Виправлено ......
J42161217

0

Октава, 42 байти

@(b,s)[(1:max(k=b.^sum(s'>32)')<=k)+32 '']

* Рядок введення / виводу не повністю відповідає регулярному вираженню, але можна зрозуміти, яка панель є.

Функція приймає в якості бази вхідних даних bі 2D масив символів, sщо містять, "!"а вихід також є масивом символів.

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

Пояснення:

                       s'>32               % logical array of input represents 1 for filler and 0 for spaces
                   sum(     )'             % an array containing length of each string 
              k=b.^                        % exponentiate ( lengths of output)
        1:max(                )            % range form 1 to max of output lengths
                               <=k         % logical array of output represents 1 for filler and 0 for spaces
      [(                          )+32 ''] % convert the logical array to char array.

0

CJam, 20 байт

q~:A;N/{,A\#"#"e*N}%

Формат введення

Введення потрібно в такому форматі:

"##
####
######"2


0

V , 27 байт

Основна ідея полягає в тому, що ми додаємо a 'до кожного рядка (n ^ 0), а потім для кожного #замінюємо 's у рядку на [input] * '. Наприкінці я поміняв усі 'на# раз

Àé'ld0ÎA'
ò/#
"_xÓ'/"òÍ'/#

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



0

05AB1E , 10 байт

U|v1Xygm×,

Первинний символ є, 1а роздільник - це новий рядок.

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

U          # Store the base in X
 |         # Get the rest of input as a list of lines
  v        # For each...
   1       #   Push 1
    X      #   Push the base
     y     #   Push this bar
      g    #   Get the length
       m   #   Push a**b
        ×, #   Print a string of #s with that length

0

Сітківка , 62 байти

ms`^(?=.*¶(.*))
#;$1$*#;
{`#(?=#*;(#+);#)
$1
}m`#$

;#+;|¶.*$

Спробуйте в Інтернеті! Зрештою, гістограма - це лише список одинакових чисел. Приймає введення як графік (з використанням #s), за яким слід базувати в десятковій частині (щоб уникнути плутанини). Пояснення: Перші замінювальні префікси 1 та основи кожного рядка графіка. Потім друга заміна множить перше число в кожному рядку на друге, поки третє число не є нульовим. Потім третя заміна зменшує третє число у кожному рядку. Ці дві заміни повторюються, поки третє число не стане нульовим. Остання заміна видаляє базу скрізь, залишаючи бажаний результат.



0

Аліса , 23 байти

/'/dI
\I!wO&K/h.n$@?~E&

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

Я не тільки не переймаюся, але я настільки зобов'язаний зробити точку належним чином, яку я використовую ! як наповнювач. Це, безумовно, приверне увагу читача.

Пояснення

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

/I/!/wI&/h.n$@?~E&\'!dOK

/I                        % input base
  /!/                     % store onto tape as integer
     w                    % push return address
      I                   % input next line
       &/h                % get length (by adding 1 for each character in the string)
          .n$@            % terminate if zero
              ?~E         % get base from tape and raise to power
                 &\'!     % push "!" onto the stack that many times
                     d    % combine into a single string
                      O   % output string with newline
                       K  % return to stored address (without popping it from the return address stack)

0

Perl 6 , 26 байт

{map '#'x$^b** *.comb,@^a}

Перелік вхідних рядків у першому параметрі @^a. Другий параметр $^b- база. Повертається список вихідних рядків.

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