Las escalas de registro son para los que abandonan


24

Todo el mundo sabe que las escalas de registro son para los que abandonan . Por lo tanto, debe escribir un programa o función que cancele la anulación de un gráfico de barras con una escala de registro dada una base.

La entrada del gráfico de barras se toma como una sola cadena, que es una lista de barras, donde cada barra del gráfico de barras de escala de registro está separada por el delimitador imprimible (o espacio en blanco) de su elección (por lo tanto, 0x09-0x0A + 0x20-0x7E) y compuesto por un carácter de relleno imprimible sin espacios en blanco (por lo tanto, 0x21-0x7E) de su elección.

El programa o función genera una sola cadena que es una lista de barras, donde cada barra está separada por el mismo delimitador por el que se separó la entrada y está compuesta por el mismo carácter de relleno de la que estaba compuesta la entrada.

Ejemplo

Elegimos un delimitador de "\ n" (una nueva línea) y un carácter de relleno de "#". La entrada que se pasa a nuestro programa o función es:

base = 2 y cadena =

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

El código encontraría que las longitudes de las barras son [4,2,6,3]. Calcularía el anti-log de cada longitud con base 2para obtener [2^4,2^2,2^6,2^3]= [16,4,64,8]. Luego, las longitudes se emiten en formato de barra de escala lineal:

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

De entrada y salida

Su programa o función puede ingresar y salir en cualquier formato razonable .

Se garantiza que la base de entrada será un número entero mayor que 1. Se puede suponer que la base es menor que 256. Se garantiza que la entrada de cadena coincida completamente con la expresión regular (f+s)+f+, donde fy sse reemplaza con su relleno y delimitador respectivamente.

La salida de la cadena debe coincidir completamente con la expresión regular (f+s)+f+, donde fy sse reemplazan con el mismo relleno y delimitador, respectivamente. La salida puede tener opcionalmente una nueva línea final.

La salida y la entrada también pueden ser una lista de cadenas en lugar de estar delimitadas por una subcadena, aunque debe ser posible comprender qué barra es cuál.

Casos de prueba

(suponga que el relleno es #y el delimitador es \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
-
#
#
##
##
#
##
#
#
#
#
##
##
#
#
##
#
-
##
##
####
####
##
####
##
##
##
##
####
####
##
##
####
##

Respuestas:


6

Función de código de máquina x86 de 32 bits, 21 bytes

Función de código de máquina x86-64, 22 bytes

El ahorro de 1B en modo de 32 bits requiere el uso de separator = filler-1, por ejemplo, fill=0y sep=/. La versión de 22 bytes puede usar una elección arbitraria de separador y relleno.


Esta es la versión de 21 bytes, con input-separator = \n(0xa), output-filler = 0, output-separator = /= filler-1. Estas constantes se pueden cambiar fácilmente.

; 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

La versión de 64 bits es 1 byte más larga, utilizando un DEC de 2 bytes o un mov al, output_separator. Aparte de eso, el código de máquina es el mismo para ambas versiones, pero algunos nombres de registro cambian (por ejemplo, en rcxlugar de ecxen el pop).

Ejemplo de salida al ejecutar el programa de prueba (base 3):

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

algoritmo :

Pase sobre la entrada, haciendo exp *= basepara cada char de relleno. En los delimitadores y el byte cero de terminación, agregue expbytes de relleno y luego un separador a la cadena de salida y restablezca a exp=1. Es muy conveniente garantizar que la entrada no termine con una nueva línea y un terminador.

En la entrada, cualquier valor de byte por encima del separador (comparación sin signo) se trata como relleno, y cualquier valor de byte por debajo del separador se trata como un marcador de fin de cadena. (La comprobación explícita de un byte cero requeriría una test al,alramificación adicional frente a la ramificación en las marcas establecidas por el bucle interno).


Las reglas solo permiten un separador final cuando se trata de una nueva línea final. Mi implementación siempre agrega el separador. Para obtener el ahorro de 1B en modo de 32 bits, esa regla requiere separador = 0xa ( '\n'ASCII LF = salto de línea), relleno = 0xb ( '\v'ASCII VT = pestaña vertical). Eso no es muy amigable para los humanos, pero satisface la letra de la ley. (Puede realizar un hexdump o
tr $'\v' xla salida para verificar que funciona, o cambiar la constante para que el separador de salida y el relleno sean imprimibles. También noté que las reglas parecen requerir que pueda aceptar entradas con el mismo relleno / sep que usa para la salida , pero no veo nada que ganar al romper esa regla).


Fuente NASM / YASM. Compile como código de 32 o 64 bits, usando las %ifcosas incluidas con el programa de prueba o simplemente cambie rcx a 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

La función sigue el x86-64 SystemV ABI, con firma
void str_exp(char *out /*rdi*/, const char *src /*rsi*/, unsigned base /*edx*/);

Solo informa al llamante de la longitud de la cadena de salida al dejarle un puntero de un paso al finalrdi , por lo que podría considerar este el valor de retorno en un no -convención de llamadas estándar.

xchg eax,ediCostaría 1 o 2 bytes ( ) devolver el puntero final en eax o rax. (Si usa el x32 ABI, se garantiza que los punteros sean de solo 32 bits; de lo contrario, tenemos que usarlos xchg rax,rdien caso de que la persona que llama pase un puntero a un búfer fuera de los 32 bits bajos). No incluí esto en la versión que estoy publicar porque hay soluciones que la persona que llama puede usar sin obtener el valor derdi , por lo que podría llamarlo desde C sin envoltorio.

Ni siquiera terminamos en nulo la cadena de salida ni nada, por lo que solo termina en nueva línea. Se necesitarían 2 bytes para arreglar eso: xchg eax,ecx / stosb (rcx es cero desde rep stosb).

Las formas de averiguar la longitud de la cadena de salida son:

  • rdi apunta al final de la cadena al regresar (para que la persona que llama pueda hacer len = end-start)
  • la persona que llama puede saber cuántas filas había en la entrada y contar nuevas líneas
  • la persona que llama puede usar un gran búfer a cero y strlen()luego.

No son bonitas ni eficientes (excepto por usar el valor de retorno RDI de una persona que llama), pero si lo desea, no llame a las funciones de golf asm desde C.: P


Limitaciones de tamaño / rango

El tamaño máximo de la cadena de salida solo está limitado por las limitaciones de espacio de direcciones de memoria virtual. (Principalmente, ese hardware x86-64 actual solo admite 48 bits significativos en direcciones virtuales, divididas por la mitad porque firman-extienden en lugar de cero-extienden. Vea el diagrama en la respuesta vinculada ).

Cada fila solo puede tener un máximo de 2 ** 32-1 bytes de relleno, ya que acumulo el exponencial en un registro de 32 bits.

La función funciona correctamente para bases de 0 a 2 ** 32 - 1. (Correcto para la base 0 es 0 ^ x = 0, es decir, solo líneas en blanco sin bytes de relleno. Correcto para la base 1 es 1 ^ x = 1, así que siempre 1 relleno por línea.)

También es increíblemente rápido en Intel IvyBridge y posterior, especialmente para grandes filas que se escriben en la memoria alineada. rep stosbes una implementación óptima memset()para grandes recuentos con punteros alineados en CPU con la función ERMSB . por ejemplo, 180 ** 4 es 0.97GB, y toma 0.27 segundos en mi i7-6700k Skylake (con ~ 256k fallas de página suaves) para escribir en / dev / null. (En Linux, el controlador de dispositivo para / dev / null no copia los datos en ninguna parte, simplemente regresa. Por lo tanto, todo el tiempo está en las rep stosbfallas de página suaves que se activan al tocar la memoria por primera vez. Es desafortunadamente no se usan páginas enormes transparentes para la matriz en el BSS. Probablemente una madvise()llamada al sistema lo aceleraría).

Programa de prueba :

Cree un binario estático y ejecútelo como ./string-exponential $'#\n##\n###' $(seq 2)para la base 2. Para evitar implementar un atoi, lo utiliza base = argc-2. (Los límites de longitud de la línea de comando evitan probar bases ridículamente grandes).

Este contenedor funciona para cadenas de salida de hasta 1 GB. (Solo hace una sola llamada al sistema write () incluso para cadenas gigantescas, pero Linux lo admite incluso para escribir en tuberías). Para contar caracteres, canalice wc -co use strace ./foo ... > /dev/nullpara ver el argumento de la llamada al sistema de escritura.

Esto aprovecha el valor de retorno RDI para calcular la longitud de la cadena como un argumento para 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 fue un desafío divertido que se prestó muy bien a asm, especialmente a las operaciones de cadena x86 . Las reglas están bien diseñadas para evitar tener que manejar una nueva línea y luego un terminador al final de la cadena de entrada.

Un exponencial con multiplicación repetida es como multiplicar con suma repetida, y de todos modos necesitaba hacer un bucle para contar los caracteres en cada fila de entrada.

Pensé en usar un operando mulo en imullugar del más largo imul r,r, pero su uso implícito de EAX entraría en conflicto con LODSB.


También probé SCASB en lugar de cargar y comparar , pero necesitaba xchg esi,ediantes y después del ciclo interno, porque SCASB y STOSB usan EDI. (Por lo tanto, la versión de 64 bits tiene que usar el x32 ABI para evitar truncar los punteros de 64 bits).

Evitar STOSB no es una opción; nada más es tan corto. Y la mitad del beneficio de usar SCASB es que AL = relleno después de abandonar el bucle interno, por lo que no necesitamos ninguna configuración para REP STOSB.

SCASB se compara en la otra dirección de lo que había estado haciendo, por lo que necesitaba revertir las comparaciones.

Mi mejor intento con xchg y scasb. Funciona, pero no es más corto. ( Código de 32 bits, usando el truco inc/ decpara cambiar el relleno al 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 una entrada de ../.../., produce ..../......../../. No me voy a molestar en mostrar un hexdump de la versión con separator = newline.


4

Mathematica 41 38 Bytes

-3 Bytes gracias a LLlAMnYP

Esto toma la entrada como una lista de cadenas seguidas de un número entero. La salida también es una lista de cadenas.

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

Explicación:

                   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

Versión anterior, 41 bytes

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

"" <> "#"~Table~#es 3 bytes más corto que "#"~StringRepeat~#, probablemente golfable aún más.
LLlAMnYP

3

Japt , 7 bytes

Toma el gráfico como una matriz de cadenas con "el relleno y la base como un entero.

£QpVpXl

Pruébalo en línea

Agregue }Ral final para tomar el gráfico como una cadena separada de nueva línea. ( Pruébalo )


Explicación

    :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 es espacio. Relleno es cualquier personaje que no sea el espacio.

Pruébalo en línea!

Explicación

       % 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

Esto no parece funcionar; la longitud de cada línea en la salida para el caso de prueba que incluyó en su TIO debe ser 9,3,27,9 pero en cambio es 6,3,9,3.
Shaggy

@ Shaggy Tienes toda la razón. Gracias por notarlo. Cometí un error en mi última edición. Regresé a la versión anterior, lo cual es correcto
Luis Mendo

No pude entender cómo funcionaba con la explicación, ¡luego hice clic en el TIO! : D
Shaggy

1
@ Shaggy Acabo de agregar una explicación para esta versión, ¡espero que sea más clara!
Luis Mendo

3

Haskell , 37 33 bytes

4 bytes recortados gracias a sudee

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

Descripción:

\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

Decepcionantemente, esto es 2 bytes mucho más corto que la versión de punto libre más difícil de leer:

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

La entrada debe ser una sola cadena
bartavelle

@bartavelle, no necesariamente.
Shaggy

Eso es lo que entiendo por La entrada del gráfico de barras se toma como una sola cadena ...
bartavelle

1
@bartavelle: la salida y la entrada también pueden ser una lista de cadenas en lugar de estar delimitadas por una subcadena, aunque debe ser posible comprender qué barra es cuál.
Julian Wolf

2
Se puede reemplazar replicate(b^length x)'#'con '#'<$[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

Pruébalo en línea!

ReRegex es como el primo feo de Retina que da todo el esfuerzo a las expresiones regulares, en lugar de tener sus propios operadores sofisticados.

Por supuesto, también tiene #importy #inputpara guardar tanto la entrada de codificación como la reescritura de las mismas expresiones una y otra vez.

Explicado.

Toma entrada en forma de:

2
____
__
______
___

en STDIN, y da salida como

________________
____
________________________________________________________________
________

En primer lugar, el programa importa la Biblioteca de Matemáticas , que por supuesto está completamente escrita en ReRegex. La mayor parte de esto es entonces tres expresiones regulares.

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

El primero coincide con nuestra base de entrada y busca una línea de unario después. luego, reemplaza esa línea con;$1^d<$4> , que es la base, al poder del (en decimal) unario. La biblioteca matemática maneja la conversión de base y el exponente. UNA ; se coloca al inicio para identificarlo luego como terminado.

El segundo, coincide con la base, luego muchas líneas de;, antes de terminar. Si esto coincide con todo, se corta la base. dejando uf con solo las respuestas y; s.

El último, coincide solo unario al inicio, opcionalmente, luego una ;respuesta. Luego transforma esa respuesta en unario nuevamente, sin el; .

Debido a que la salida no coincide con la primera expresión regular, no se repite infinitamente, por lo que nuestra solución se genera.



2

Röda , 19 bytes

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

Pruébalo en línea!

Toma una matriz como entrada y devuelve una secuencia de valores como salida.

Explicació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 bytes

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

Pruébalo en línea! Ejemplo de uso: f 3 ["##","#","###","#"]devoluciones ["#########","###","###########################","###"].

Úselo mapM putStrLn $ f 3 ["##","#","###","#"]para obtener un resultado visualmente más agradable:

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

Solo comento aquí porque no puedo comentar sobre la publicación que eliminó ... intente sum[sum[]^sum[],sum[]^sum[]].
Ørjan Johansen

2

05AB1E , 9 bytes

Las barras están separadas por espacios, el carácter de salida es el mismo que el carácter de entrada.

¬Š#€gm×ðý

Pruébalo en línea!

¬Š#€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),"#")."
";

Pruébalo en línea!


Esto regresa con una nueva línea principal, que no está permitida por la expresión regular. Puede usar en [str_pad]."\n"lugar de "\n".[str_pad]arreglar esto (+1 byte). Además, puede suponer cuál es el relleno, por lo que podría guardar dos bytes $l[0]cambiándolo a "#".
fireflame241

@ fireflame241 Hecho Gracias
Jörg Hülsermann

1

Jalea , 7 bytes

ṁL*@¥¥€

Un enlace monádico que toma y devuelve listas de las barras (listas de caracteres, cadenas AKA), el carácter de relleno es flexible.

Pruébalo en línea! (el pie de página embellece la lista resultante uniendo sus elementos con nuevas líneas).

¿Cómo?

ṁ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€*@¥- obtenga la longitud de cada barra ( L€), aumente basea esa potencia ( *@), luego comprima ( ") la lista y aplique la diada de molde ( ) entre las dos.


4 rápidos y 3 enlaces reales? Este desafío es bastante pesado para controlar el flujo de datos ...
ETHproductions

Sí, podría haber una solución más corta disponible ...
Jonathan Allan

@ JonathanAllan Me temo que no lo hay.
Erik the Outgolfer

@ETHproductions En realidad es un enlace en su conjunto. La explicación podría haber sido solo una línea.
Erik the Outgolfer

1

Ruby , 29 bytes

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

Pruébalo en línea!

Sí, descubrí la semana pasada que ?#produce una cadena de un solo carácter. No tengo idea de por qué existe esta función, pero estoy seguro de que lo hace.


1
El ?Xoperador, donde Xhay algún carácter, es el operador "obtener la representación predeterminada de este carácter". En Ruby <1.9, devolvería el punto de código Unicode del carácter, porque así es como se definieron los caracteres, pero ahora devuelve una cadena que contiene el carácter. Es parte de un cambio general hacia un manejo Unicode más consistente en Ruby.
Tutleman

@Turtleman, ¿hay alguna pasa histérica por qué ?Xse usa? Muchas convenciones más extravagantes de Ruby, como la gran cantidad de $variables, existen debido a la familiaridad con Perl.
ymbirtt

1

JavaScript (ES8), 39 bytes

Toma la base como un número entero y el gráfico como una matriz de cadenas con cualquier carácter como relleno, utilizando la sintaxis de curry.

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

Intentalo

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 versión toma el gráfico como una cadena separada de nueva línea, nuevamente con cualquier carácter como relleno.

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

No piense que necesita la mbandera en la expresión regular, por defecto .no coincide con las nuevas líneas.
ETHproductions

Hmm, no sé de dónde vino eso: los peligros de intentar jugar golf desde un teléfono. Gracias por señalarlo, @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 ... Solucionado ......
J42161217

0

Octava, 42 bytes

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

* La entrada / salida de la cadena no coincide completamente con la expresión regular, pero es posible entender qué barra es cuál.

Una función toma como base de entrada by una matriz 2D de caracteres que scontiene "!"y la salida también es una matriz de caracteres.

Pruébalo en línea!

Explicación:

                       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

Se requiere entrada en el siguiente formato:

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

0

Carbón , 11 bytes

NβWS«PXβLι↓

Pruébalo en línea! El enlace es a la versión detallada del código. I / O es como una lista de cadenas de -caracteres (tenga en cuenta que necesita una línea vacía para terminar la lista).


0

V , 27 bytes

La idea básica es que agreguemos un 'a cada fila (n ^ 0), y luego para cada uno #reemplazamos el 's en la línea con [input] * '. Al final cambié todo el 'de #nuevo

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

Pruébalo en línea!


0

R , 35 bytes

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

Una función anónima que toma las cadenas como una lista y la base, y devuelve una lista de cadenas.

Pruébalo en línea!


0

05AB1E , 10 bytes

U|v1Xygm×,

El carácter del archivador es 1y el delimitador es una nueva línea.

Pruébalo en línea!

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`#$

;#+;|¶.*$

Pruébalo en línea! Después de todo, un gráfico de barras es solo una lista de números unarios. Toma la entrada como el gráfico (usando #s) seguido de la base en decimal (para evitar confusiones). Explicación: El primer reemplazo de prefijos 1 y la base de cada línea del gráfico. El segundo reemplazo luego multiplica el primer número en cada línea por el segundo, siempre que el tercer número sea distinto de cero. El tercer reemplazo luego disminuye el tercer número en cada línea. Estos dos reemplazos se repiten hasta que el tercer número se convierte en cero. El último reemplazo elimina la base en todas partes, dejando el resultado deseado.



0

Alice , 23 bytes

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

Pruébalo en línea!

No solo no soy una persona que deja de fumar, sino que estoy tan comprometido a hacer el punto correctamente que uso ! como relleno. Eso sin duda llamará la atención del lector.

Explicación

Los espejos se retienen en esta explicación para que quede más claro cuando el programa cambia entre los modos cardinal y 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}

La lista de cadenas de entrada está en el primer parámetro, @^a. El segundo parámetro $^bes la base. Se devuelve una lista de cadenas de salida.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.