As escalas de log são para desistentes


24

Todo mundo sabe que as escalas de log são para desistentes . Portanto, você deve escrever um programa ou função que desqualifique um gráfico de barras com uma escala de log dada uma base.

A entrada do gráfico de barras é tomada como uma única sequência, que é uma lista de barras, onde cada barra do gráfico de barras da escala de log é separada pelo delimitador imprimível (ou espaço em branco) de sua escolha (portanto, 0x09-0x0A + 0x20-0x7E) e composto por um caractere de preenchimento que não seja um espaço em branco imprimível (portanto, 0x21-0x7E) de sua escolha.

O programa ou função gera uma única sequência de caracteres que é uma lista de barras, onde cada barra é separada pelo mesmo delimitador pelo qual a entrada foi separada e é composta pelo mesmo caractere de preenchimento da entrada.

Exemplo

Nós escolhemos um delimitador de "\ n" (uma nova linha) e um caractere de preenchimento de "#". A entrada passada para o nosso programa ou função é:

base = 2 e string =

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

O código descobriria que os comprimentos das barras são [4,2,6,3]. Ele calcularia o anti-log de cada comprimento com base 2para obter [2^4,2^2,2^6,2^3]= [16,4,64,8]. Em seguida, os comprimentos são emitidos no formato de barra de escala linear:

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

Entrada / Saída

Seu programa ou função pode entrar e sair em qualquer formato razoável .

É garantido que a base de entrada seja um número inteiro maior que 1. Você pode supor que a base seja menor que 256. A entrada de sequência é garantida para corresponder totalmente ao regex (f+s)+f+, onde fe sé substituída por seu preenchedor e delimitador, respectivamente.

A saída da sequência deve corresponder totalmente à regex (f+s)+f+, onde fe sé substituída pelo mesmo preenchedor e delimitador, respectivamente. A saída pode opcionalmente ter uma nova linha à direita.

A saída e a entrada também podem ser uma lista de cadeias, em vez de serem delimitadas por uma substring, embora seja necessário entender qual barra é qual.

Casos de teste

(suponha que o preenchimento seja #e o delimitador seja \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
-
#
#
##
##
#
##
#
#
#
#
##
##
#
#
##
#
-
##
##
####
####
##
####
##
##
##
##
####
####
##
##
####
##

Respostas:


6

função de código de máquina x86 de 32 bits, 21 bytes

função de código de máquina x86-64, 22 bytes

A economia de 1B no modo de 32 bits requer o uso de separator = filler-1, por exemplo, fill=0e sep=/. A versão de 22 bytes pode usar uma escolha arbitrária de separador e preenchedor.


Esta é a versão de 21 bytes, com separador de entrada = \n(0xa), preenchedor de 0saída = , separador de saída = /= preenchedor-1. Essas constantes podem ser facilmente alteradas.

; 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

A versão de 64 bits é 1 byte mais longa, usando um DEC de 2 bytes ou a mov al, output_separator. Fora isso, o código da máquina é o mesmo para as duas versões, mas alguns nomes de registros são alterados (por exemplo, em rcxvez de ecxnopop ).

Exemplo de saída da execução do programa de teste (base 3):

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

Algoritmo :

Faça um loop sobre a entrada, fazendo exp *= basepara cada caractere de preenchimento. Nos delimitadores e no byte zero final, acrescente expbytes de preenchimento e, em seguida, um separador à sequência de saída e redefina para exp=1. É muito conveniente garantir que a entrada não termine com uma nova linha e um terminador.

Na entrada, qualquer valor de byte acima do separador (comparação não assinada) é tratado como preenchedor e qualquer valor de byte abaixo do separador é tratado como um marcador de fim de cadeia. (A verificação explícita de um byte zero levaria um tempo extra test al,alvs. ramificação nos sinalizadores definidos pelo loop interno).


As regras permitem apenas um separador à direita quando é uma nova linha à direita. Minha implementação sempre anexa o separador. Para obter o salvamento de 1B no modo de 32 bits, essa regra requer separador = 0xa ( '\n'ASCII LF = avanço de linha), preenchedor = 0xb ( '\v'ASCII VT = guia vertical). Isso não é muito amigável ao ser humano, mas satisfaz a letra da lei. (Você pode fazer o hexdump ou
tr $'\v' xa saída para verificar se funciona ou alterar a constante para que o separador e o preenchedor de saída sejam imprimíveis. Notei também que as regras parecem exigir que ele aceite entradas com o mesmo preenchimento / sep usado para saída , mas não vejo nada a ganhar por violar essa regra.).


Fonte NASM / YASM. Crie como código de 32 ou 64 bits, usando o %ifmaterial incluído no programa de teste ou apenas altere rcx para 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

A função segue a ABI do x86-64 SystemV, com assinatura.
void str_exp(char *out /*rdi*/, const char *src /*rsi*/, unsigned base /*edx*/);

Ele informa o chamador apenas do comprimento da sequência de saída, deixando um ponteiro de um passado para o final para que rdivocê possa considerar esse valor de retorno em um valor não convenção de chamada padrão.

xchg eax,ediCustaria 1 ou 2 bytes ( ) para retornar o ponteiro final em eax ou rax. (Se você estiver usando a ABI x32, é garantido que os ponteiros têm apenas 32 bits, caso contrário, temos que usá xchg rax,rdi-lo caso o chamador passe um ponteiro para um buffer fora dos baixos 32 bits.) Eu não o incluí na versão em que estou postagem porque existem soluções alternativas que o chamador pode usar sem obter o valor rdi, portanto, você pode chamar isso de C sem invólucro.

Nós nem terminamos nulos a string de saída ou algo assim, portanto, é apenas terminada em nova linha. Seria necessário 2 bytes para corrigir isso: xchg eax,ecx / stosb (rcx é zero de rep stosb.)

As maneiras de descobrir o comprimento da string de saída são:

  • rdi aponta para um ponto após o final da string no retorno (para que o chamador possa fazer len = end-start)
  • o chamador pode apenas saber quantas linhas estavam na entrada e contar novas linhas
  • o chamador pode usar um buffer zerado grande e strlen()depois.

Eles não são bonitos ou eficientes (exceto para usar o valor de retorno RDI de um chamador asm), mas se você desejar, não chame as funções golfadas de asm de C.: P


Limitações de tamanho / faixa

O tamanho máximo da sequência de saída é limitado apenas pelas limitações de espaço de endereço da memória virtual. (Principalmente, o hardware atual x86-64 suporta apenas 48 bits significativos em endereços virtuais, divididos ao meio porque eles estendem o sinal em vez do zero. Veja o diagrama na resposta vinculada .)

Cada linha pode ter no máximo 2 ** 32-1 bytes de preenchimento, pois acumulo o exponencial em um registro de 32 bits.

A função funciona corretamente para bases de 0 a 2 ** 32 - 1. (Correta para a base 0 é 0 ^ x = 0, ou seja, apenas linhas em branco sem bytes de preenchimento. Correta para a base 1 é 1 ^ x = 1, portanto, sempre 1 preenchimento por linha.)

Também é incrivelmente rápido no Intel IvyBridge e posterior, especialmente para grandes linhas sendo gravadas na memória alinhada. rep stosbé uma implementação ideal memset()para contagens grandes com ponteiros alinhados em CPUs com o recurso ERMSB . por exemplo, 180 ** 4 tem 0,97 GB e leva 0,27 segundos no meu Skylake i7-6700k (com ~ 256k falhas de página suaves) para gravar em / dev / null. (No Linux, o driver de dispositivo para / dev / null não copia os dados em lugar algum, apenas retorna. Portanto, o tempo todo ocorre nas rep stosbfalhas de página e soft que são acionadas ao tocar na memória pela primeira vez. infelizmente, não usando grandes páginas transparentes para a matriz no BSS.madvise() chamada do sistema aceleraria isso.)

Programa de teste :

Crie um binário estático e execute como ./string-exponential $'#\n##\n###' $(seq 2)na base 2. Para evitar a implementação de um atoi, ele usa base = argc-2. (Os limites de comprimento da linha de comando impedem o teste de bases ridiculamente grandes.)

Esse wrapper funciona para cadeias de saída de até 1 GB. (Ele faz apenas uma chamada do sistema write () mesmo para strings gigantes, mas o Linux suporta isso mesmo para gravação em pipes). Para contar caracteres, canalize wc -cou use strace ./foo ... > /dev/nullpara ver o argumento no syscall de gravação.

Isso aproveita o valor de retorno da RDI para calcular o comprimento da sequência como argumento 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.

Este foi um desafio divertido que se prestou muito bem ao asm, especialmente às operações de sequência x86 . As regras foram bem projetadas para evitar a necessidade de lidar com uma nova linha e, em seguida, com um terminador no final da string de entrada.

Um exponencial com multiplicação repetida é como multiplicar com adição repetida, e eu precisava fazer um loop para contar caracteres em cada linha de entrada de qualquer maneira.

Eu considerei usar um operando mulou em imulvez de mais imul r,r, mas seu uso implícito do EAX entraria em conflito com o LODSB.


Também tentei o SCASB em vez de carregar e comparar , mas eu precisava xchg esi,ediantes e depois do loop interno, porque o SCASB e o STOSB usam EDI. (Portanto, a versão de 64 bits precisa usar a ABI x32 para evitar truncar ponteiros de 64 bits).

Evitar o STOSB não é uma opção; nada mais é tão curto. E metade do benefício de usar o SCASB é que AL = filler depois de sair do loop interno, portanto, não precisamos de nenhuma configuração para o REP STOSB.

O SCASB se compara na outra direção do que eu estava fazendo, então eu precisava reverter as comparações.

Minha melhor tentativa com xchg e scasb. Funciona, mas não é mais curto. ( Código de 32 bits, usando o truque inc/ decpara alterar o preenchimento em separador ).

; 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    

Para uma entrada de ../.../., produz ..../......../../. Não vou me incomodar em mostrar um hexdump da versão com separator = newline.


4

Mathematica 41 38 Bytes

-3 bytes graças a LLlAMnYP

Isso leva a entrada como uma lista de cadeias seguidas por um número inteiro. Saída também é uma lista de strings.

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

Explicação:

                   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

Versão antiga, 41 bytes

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

"" <> "#"~Table~#é 3 bytes mais curto que "#"~StringRepeat~#, provavelmente também mais jogável.
LLlAMnYP

3

Japonês , 7 bytes

Toma o gráfico como uma matriz de seqüências de caracteres com "o preenchedor e a base como um número inteiro.

£QpVpXl

Experimente online

Adicione }Rao final para obter o gráfico como uma sequência separada por nova linha. ( Experimente )


Explicação

    :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 bytes

Y'iw^1HL(Y"

Delimitador é espaço. Preenchimento é qualquer caractere que não seja o espaço.

Experimente online!

Explicação

       % 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

Isso não parece funcionar; o comprimento de cada linha na saída do caso de teste incluído no seu TIO deve ser 9,3,27,9, mas em vez disso é 6,3,9,3.
34

@ Shaggy Você está totalmente certo. Obrigado por perceber. Cometi um erro na minha edição mais recente. Tenho revertida para a versão anterior, ehich está correto
Luis Mendo

Não consegui descobrir como estava funcionando a partir da explicação - então eu cliquei no TIO! : D
Shaggy

11
@ Shagy Acabei de adicionar uma explicação para esta versão, espero que mais clara!
Luis Mendo

3

Haskell , 37 33 bytes

4 bytes cortados graças ao sudee

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

Descrição:

\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

Infelizmente, isso é 2 bytes muito mais curto que a versão pointfree, mais difícil de ler:

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

A entrada deve ser uma única corda
bartavelle

@ bartavelle, não necessariamente.
Shaggy

Isso é o que eu entendo por A entrada gráfico de barras é tomado como uma única corda ...
bartavelle

11
@ bartavelle: A saída e a entrada também podem ser uma lista de strings, em vez de serem delimitadas por uma substring, embora seja necessário entender qual barra é qual.
Julian Lobo

2
Você pode substituir replicate(b^length x)'#'por '#'<$[1..b^length x].
Sudee

3

ReRegex , 105 bytes

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

Experimente online!

ReRegex é como o primo feio de Retina que dá a todos o esforço às expressões regulares, em vez de ter seus próprios operadores sofisticados.

Obviamente, ele também tem #importe #inputsalva as entradas codificadas e reescreve as mesmas expressões repetidamente.

Explicado.

Recebe entrada na forma de:

2
____
__
______
___

em STDIN, e fornece saída como

________________
____
________________________________________________________________
________

Primeiramente, o programa importa a Biblioteca de Matemática , que obviamente está totalmente escrita em ReRegex. A maior parte disso são três expressões regulares.

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

O primeiro corresponde à nossa base de entrada e busca uma linha de unário depois dela. então, substitui essa linha por ;$1^d<$4>, que é a base, pelo poder do Unário (Decimal). A biblioteca de matemática lida com a conversão base e o expoente. UMA ; é colocado no início para identificá-lo mais tarde como concluído.

O segundo, corresponde à base, depois a muitas linhas de;, antes de terminar. Se isso corresponder à coisa toda, ele cortará a base. deixando uf apenas com as respostas ;es.

O último corresponde apenas a unário no início, opcionalmente, e em seguida uma ;resposta. Em seguida, transforma essa resposta em unária novamente, sem o ;.

Como a saída não é correspondida pelo primeiro regex, ela não executa um loop infinito e, portanto, nossa solução é gerada.



2

Röda , 19 bytes

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

Experimente online!

Pega uma matriz como entrada e retorna um fluxo de valores como saída.

Explicação

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 bytes

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

Experimente online! Exemplo de uso: f 3 ["##","#","###","#"]retorna["#########","###","###########################","###"] .

Use mapM putStrLn $ f 3 ["##","#","###","#"]para obter uma saída mais agradável visualmente:

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

Apenas comentando aqui porque não posso comentar a postagem que você excluiu ... tente sum[sum[]^sum[],sum[]^sum[]].
Ørjan Johansen

2

05AB1E , 9 bytes

As barras são separadas por espaços, o caractere de saída é o mesmo que o caractere de entrada.

¬Š#€gm×ðý

Experimente online!

¬Š#€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 bytes

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

Experimente online!


Isso retorna com uma nova linha principal, que não é permitida pela regex. Você pode usar em [str_pad]."\n"vez de "\n".[str_pad]corrigir isso (+1 byte). Além disso, você pode assumir qual é o preenchimento, para poder salvar dois bytes $l[0]alterando-o para "#".
Fireflame241

@ fireflame241 Feito Obrigado
Jörg Hülsermann

1

Geléia , 7 bytes

ṁL*@¥¥€

Um link monádico que recebe e retorna listas de barras (elas mesmas listas de caracteres, seqüências AKA), o caractere de preenchimento é flexível.

Experimente online!(o rodapé pré-define a lista resultante juntando seus elementos a novas linhas.)

Quão?

ṁ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 "########")

Alternativa de 7 bytes: ṁ"L€*@¥- obtenha o comprimento de cada barra ( L€), aumente basea potência ( *@), depois compacte ( ") a lista e aplique a díade do molde ( ) entre as duas.


4 quicks e 3 links reais? Este desafio é bastante pesado em controlar o fluxo de dados ...
ETHproductions

Sim, pode haver uma solução mais curta disponível ...
Jonathan Allan

@ JonathanAllan Receio que não exista.
Erik the Outgolfer

@ETHproductions Na verdade, é um link como um todo. A explicação poderia ter sido apenas uma linha.
Erik the Outgolfer

1

Ruby , 29 bytes

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

Experimente online!

Sim, descobri na semana passada que ?#produz uma sequência de caracteres únicos. Eu não tenho idéia do porquê esse recurso existe, mas estou feliz que sim.


11
O ?Xoperador, onde Xhá algum caractere, é o operador "obter a representação padrão desse caractere". Em Ruby <1.9, ele retornaria o ponto de código Unicode do caractere, porque é assim que os caracteres foram definidos, mas agora retorna uma string contendo o caractere. É parte de uma mudança geral para um manuseio Unicode mais consistente no Ruby.
31517 Tutleman

@ Turtleman, há alguma passa histérica para por que ?Xé usada? Muitas convenções mais peculiares de Ruby, como a infinidade de $variáveis, existem por causa da familiaridade com Perl.
Ymbirtt

1

JavaScript (ES8), 39 bytes

Toma a base como um número inteiro e o gráfico como uma matriz de seqüências de caracteres com qualquer caractere como preenchedor, usando a sintaxe de currying.

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

Tente

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>


Alternativa, 49 bytes

Esta versão utiliza o gráfico como uma sequência separada por nova linha, novamente com qualquer caractere como preenchedor.

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

Não pense que você precise da mbandeira na regex, por padrão .não corresponde a novas linhas.
ETHproductions

Hmm, não sei de onde isso veio - os perigos de tentar jogar golfe a partir de um telefone. Obrigado por apontar, @ETHproductions.
Shaggy

0

Mathematica, 86 bytes

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

entrada

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


ok ... Corrigido ......
J42161217

0

Oitava, 42 bytes

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

* A entrada / saída da string não corresponde totalmente ao regex, mas é possível entender qual barra é qual.

Uma função assume como base de entrada be uma matriz 2D de caracteres scontendo"!" e a saída também é uma matriz de caracteres.

Experimente online!

Explicação:

                       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 bytes

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

Formato de entrada

A entrada é necessária no seguinte formato:

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

0

Carvão , 11 bytes

NβWS«PXβLι↓

Experimente online! Link é a versão detalhada do código. E / S é uma lista de cadeias de -caracteres (observe que você precisa de uma linha vazia para finalizar a lista).


0

V , 27 bytes

A idéia básica é que adicionemos a 'a cada linha (n ^ 0) e, em seguida #, substitua os 's na linha por cada [input] * '. No final eu troquei toda a 'para #novamente

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

Experimente online!


0

R , 35 bytes

function(s,b)strrep('#',b^nchar(s))

uma função anônima que pega as strings como uma lista e a base e retorna uma lista de strings.

Experimente online!


0

05AB1E , 10 bytes

U|v1Xygm×,

O caractere do arquivador é 1 e o delimitador é uma nova linha.

Experimente online!

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

Retina , 62 bytes

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

;#+;|¶.*$

Experimente online! Afinal, um gráfico de barras é apenas uma lista de números unários. Aceita a entrada como o gráfico (usando #s) seguido pela base em decimal (para evitar confusão). Explicação: O primeiro substituto prefixa 1 e a base para cada linha do gráfico. A segunda substituição multiplica o primeiro número de cada linha pela segunda, desde que o terceiro número seja diferente de zero. A terceira substituição então diminui o terceiro número em cada linha. Essas duas substituições são repetidas até o terceiro número se tornar zero. A última substituição exclui a base em todos os lugares, deixando o resultado desejado.



0

Alice , 23 bytes

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

Experimente online!

Não só não sou um desistente, mas estou tão comprometido em fazer o argumento corretamente que uso ! como preenchedor. Isso certamente chamará a atenção do leitor.

Explicação

Os espelhos são retidos nesta explicação para torná-la mais clara quando o programa alterna entre os modos cardinal e ordinal.

/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 bytes

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

A lista de cadeias de entrada está no primeiro parâmetro @^a,. O segundo parâmetro $^bé a base. Uma lista de cadeias de saída é retornada.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.