Le scale del log sono per Quitters


24

Tutti sanno che le scale di log sono per chi esce . Pertanto, è necessario scrivere un programma o una funzione che de-quitifica un grafico a barre con una scala di registro con una base.

L'input del grafico a barre viene considerato come una singola stringa che è un elenco di barre, in cui ciascuna barra del grafico a barre della scala del registro è separata dal delimitatore stampabile (o bianco) di tua scelta (quindi 0x09-0x0A + 0x20-0x7E) e composto da un carattere di riempimento stampabile non bianco (quindi 0x21-0x7E) di tua scelta.

Il programma o la funzione genera una singola stringa che è un elenco di barre, in cui ciascuna barra è separata dallo stesso delimitatore da cui è stato separato l'input ed è composto dallo stesso carattere di riempimento da cui era composto l'input.

Esempio

Scegliamo un delimitatore di "\ n" (una nuova riga) e un carattere di riempimento di "#". L'input passato al nostro programma o funzione è:

base = 2 e stringa =

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

Il codice troverebbe che le lunghezze delle barre sono [4,2,6,3]. Calcola l'anti-log di ogni lunghezza con base 2per ottenere [2^4,2^2,2^6,2^3]= [16,4,64,8]. Quindi, le lunghezze vengono emesse in formato barra lineare:

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

Input Output

Il programma o la funzione possono essere inseriti e stampati in qualsiasi formato ragionevole .

La base di input è garantita per essere un numero intero maggiore di 1. Si può presumere che la base sia inferiore a 256. L'input della stringa è garantito per corrispondere completamente al regex (f+s)+f+, dove fe ssono sostituiti rispettivamente con il filler e il delimitatore.

L'output della stringa deve corrispondere completamente al regex (f+s)+f+, dove fe ssono sostituiti rispettivamente con lo stesso filler e delimitatore. L'output può facoltativamente avere una nuova riga finale.

L'output e l'input possono anche essere un elenco di stringhe anziché delimitate da una sottostringa, anche se deve essere possibile capire quale barra è quale.

Casi test

(supponiamo che il filler sia #e il delimitatore sia \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
-
#
#
##
##
#
##
#
#
#
#
##
##
#
#
##
#
-
##
##
####
####
##
####
##
##
##
##
####
####
##
##
####
##

Risposte:


6

x86 Funzione codice macchina a 32 bit, 21 byte

funzione codice macchina x86-64, 22 byte

1B salvataggio in modalità a 32 bit richiede utilizzando separatore = riempitivo-1, ad esempio fill=0e sep=/. La versione a 22 byte può utilizzare una scelta arbitraria di separatore e riempimento.


Questa è la versione a 21 byte, con input-separator = \n(0xa), output-filler = 0, output-separator = /= filler-1. Queste costanti possono essere facilmente modificate.

; 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 versione a 64 bit è più lunga di 1 byte, usando un DEC a 2 byte o a mov al, output_separator. A parte questo, il codice macchina è lo stesso per entrambe le versioni, ma alcuni nomi di registro cambiano (ad es. rcxAnziché ecxin pop).

Esempio di output dall'esecuzione del programma di test (base 3):

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

Algoritmo :

Passa sopra l'input, facendo exp *= baseper ogni carattere di riempimento. Sui delimitatori e sul byte zero finale, aggiungere expbyte di riempimento e quindi un separatore alla stringa di output e reimpostare su exp=1. È molto comodo che l'ingresso sia garantito per non terminare con una nuova riga e un terminatore.

All'input, qualsiasi valore di byte al di sopra del separatore (confronto senza segno) viene trattato come filler e qualsiasi valore di byte al di sotto del separatore viene trattato come un marker di fine stringa. (Il controllo esplicito di un byte zero richiederebbe un extra test al,alrispetto alla ramificazione sui flag impostati dal loop interno).


Le regole consentono un separatore finale solo quando si tratta di una nuova riga finale. La mia implementazione aggiunge sempre il separatore. Per ottenere il salvataggio 1B in modalità a 32 bit, quella regola richiede separatore = 0xa ( '\n'ASCII LF = avanzamento riga), filler = 0xb ( '\v'ASCII VT = scheda verticale). Non è molto amico degli umani, ma soddisfa la lettera della legge. (È possibile eseguire
tr $'\v' xil dump esadecimale o l'output per verificare che funzioni o modificare la costante in modo che il separatore di output e il filler siano stampabili. Ho anche notato che le regole sembrano richiedere che possa accettare input con lo stesso riempimento / sep che utilizza per l'output , ma non vedo nulla da guadagnare infrangendo quella regola.).


Fonte NASM / YASM. Costruisci come codice a 32 o 64 bit, usando le %ifcose incluse con il programma di test o cambia semplicemente rcx in 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 funzione segue l'ABI SystemV x86-64, con firma
void str_exp(char *out /*rdi*/, const char *src /*rsi*/, unsigned base /*edx*/);

Informa solo il chiamante della lunghezza della stringa di output lasciando in essa un puntatore uno-oltre-fine rdi, quindi è possibile considerare questo valore di ritorno in un non convenzione di chiamata standard.

xchg eax,ediCosterebbe 1 o 2 byte ( ) per restituire il puntatore finale in eax o rax. (Se si utilizza l'ABI x32, i puntatori sono garantiti solo a 32 bit, altrimenti dobbiamo usarli xchg rax,rdinel caso in cui il chiamante passi un puntatore a un buffer esterno ai 32 bit bassi.) Non ho incluso questo nella versione pubblicazione perché esistono soluzioni alternative che il chiamante può utilizzare senza ottenere il valore da rdi, quindi è possibile chiamarlo da C senza wrapper.

Non terminiamo nemmeno con null la stringa di output o altro, quindi è solo terminata da nuova riga. Ci vorrebbero 2 byte per risolvere questo: xchg eax,ecx / stosb (rcx è zero da rep stosb.)

I modi per scoprire la lunghezza della stringa di output sono:

  • rdi punta a uno-oltre-la-fine della stringa al ritorno (quindi il chiamante può fare len = end-start)
  • il chiamante può semplicemente sapere quante righe c'erano nell'input e contare le nuove righe
  • il chiamante può utilizzare un buffer azzerato di grandi dimensioni e strlen()successivamente.

Non sono belli o efficienti (tranne per l'utilizzo del valore di ritorno RDI da un chiamante asm), ma se lo desideri, non chiamare le funzioni asm golfate da C.: P


Limitazioni di dimensioni / intervallo

La dimensione massima della stringa di output è limitata solo dalle limitazioni dello spazio indirizzo della memoria virtuale. (Principalmente che l'attuale hardware x86-64 supporta solo 48 bit significativi negli indirizzi virtuali, divisi a metà perché firmano estensione anziché estensione zero. Vedi il diagramma nella risposta collegata .)

Ogni riga può avere solo un massimo di 2 ** 32 - 1 byte di riempimento, poiché accumulo l'esponenziale in un registro a 32 bit.

La funzione funziona correttamente per le basi da 0 a 2 ** 32 - 1. (La correzione per la base 0 è 0 ^ x = 0, ovvero solo righe vuote senza byte di riempimento. La correzione per la base 1 è 1 ^ x = 1, quindi sempre 1 riempimento per riga.)

È anche incredibilmente veloce su Intel IvyBridge e versioni successive, specialmente per le righe di grandi dimensioni che vengono scritte nella memoria allineata. rep stosbè un'implementazione ottimale di memset()grandi conteggi con puntatori allineati su CPU con la funzione ERMSB . es. 180 ** 4 è 0,97 GB e impiega 0,27 secondi sul mio i7-6700k Skylake (con ~ 256k errori di pagina morbida) per scrivere su / dev / null. (Su Linux il driver di dispositivo per / dev / null non copia i dati da nessuna parte, ma semplicemente ritorna. Quindi tutto il tempo è nei rep stosbe dei difetti della pagina morbida che si innesca quando si tocca la memoria per la prima volta. È purtroppo non usando hugepage trasparenti per l'array in BSS. Probabilmente una madvise()chiamata di sistema lo accelererebbe.)

Programma di test :

Costruisci un binario statico ed eseguilo come ./string-exponential $'#\n##\n###' $(seq 2)per la base 2. Per evitare di implementare un atoi, usa base = argc-2. (I limiti di lunghezza della riga di comando impediscono di testare basi ridicolmente grandi.)

Questo wrapper funziona per stringhe di output fino a 1 GB. (Fa solo una singola chiamata di sistema write () anche per stringhe gigantesche, ma Linux lo supporta anche per scrivere su pipe). Per contare i caratteri, esegui il pipe wc -co usa strace ./foo ... > /dev/nullper vedere l'arg nella call syscall.

Questo sfrutta il valore di ritorno RDI per calcolare la lunghezza della stringa come argomento per 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.

Questa è stata una sfida divertente che si è prestata molto bene ad asm, in particolare operazioni su stringhe x86 . Le regole sono ben progettate per evitare di dover gestire una nuova riga e quindi un terminatore alla fine della stringa di input.

Un esponenziale con moltiplicazioni ripetute è proprio come moltiplicarsi con addizioni ripetute, e ho comunque bisogno di fare un ciclo per contare i caratteri in ogni riga di input.

Ho preso in considerazione l'uso di un operando mulo imulinvece del più lungo imul r,r, ma il suo uso implicito di EAX sarebbe in conflitto con LODSB.


Ho anche provato SCASB invece di caricare e confrontare , ma avevo bisogno xchg esi,ediprima e dopo il ciclo interno, perché SCASB e STOSB usano entrambi EDI. (Quindi la versione a 64 bit deve usare l'ABI x32 per evitare di troncare i puntatori a 64 bit).

Evitare STOSB non è un'opzione; nient'altro è vicino come breve. E metà del vantaggio dell'utilizzo di SCASB è che AL = filler dopo aver lasciato il loop interno, quindi non abbiamo bisogno di alcuna configurazione per REP STOSB.

SCASB si confronta nell'altra direzione rispetto a quello che avevo fatto, quindi ho dovuto invertire i confronti.

Il mio miglior tentativo con xchg e scasb. Funziona, ma non è più corto. (Codice a 32 bit, usando il inc/ dectrucco per cambiare riempitore in separatore ).

; 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    

Per un input di ../.../., produce ..../......../../. Non mi preoccuperò di mostrare un hexdump della versione con separator = newline.


4

Mathematica 41 38 byte

-3 byte grazie a LLlAMnYP

Questo accetta l'input come un elenco di stringhe seguito da un numero intero. L'output è anche un elenco di stringhe.

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

Spiegazione:

                   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

Vecchia versione, 41 byte

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

"" <> "#"~Table~#è di 3 byte più breve di "#"~StringRepeat~#, probabilmente anche ulteriormente giocabile.
LLlAMnYP,

3

Japt , 7 byte

Prende il grafico come una matrice di stringhe con "come riempitivo e la base come un numero intero.

£QpVpXl

Provalo online

Aggiungi }Ralla fine per prendere invece il grafico come una stringa separata da nuova riga. ( Provalo )


Spiegazione

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

Y'iw^1HL(Y"

Il delimitatore è spazio. Filler è qualsiasi carattere diverso dallo spazio.

Provalo online!

Spiegazione

       % 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

Questo non sembra funzionare; la lunghezza di ciascuna riga nell'output per il test case che hai incluso nel tuo TIO dovrebbe essere 9,3,27,9 ma invece è 6,3,9,3.
Shaggy,

@Shaggy Hai perfettamente ragione. Grazie per averlo notato. Ho fatto un errore nella mia ultima modifica. Sono tornato alla versione precedente, ehich è corretto
Luis Mendo

Non sono riuscito a capire come funzionasse dalla spiegazione, quindi ho fatto clic su TIO! : D
Shaggy,

1
@Shaggy Ho appena aggiunto una spiegazione per questa versione, si spera più chiara!
Luis Mendo,

3

Haskell , 37 33 byte

4 byte eliminati grazie al sudee

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

Descrizione:

\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

Deludentemente, si tratta di 2 byte molto più brevi rispetto alla versione pointfree più difficile da leggere:

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

L'input dovrebbe essere una singola stringa
bartavelle

@bartavelle, non necessariamente.
Shaggy,

Questo è quello che ho capito da The input grafico a barre è preso come una singola stringa ...
bartavelle

1
@bartavelle: l'output e l'input possono anche essere un elenco di stringhe anziché delimitate da una sottostringa, anche se deve essere possibile capire quale barra è quale.
Julian Wolf,

2
È possibile sostituire replicate(b^length x)'#'con '#'<$[1..b^length x].
sudee,

3

ReRegex , 105 byte

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

Provalo online!

ReRegex è come il brutto cugino di Retina che dedica tutto lo sforzo alle espressioni regolari, invece di avere i propri operatori fantasiosi.

Naturalmente, ha anche #importe #inputper salvare sia l'input hardcoding, sia riscrivere le stesse espressioni più e più volte.

Ha spiegato.

Accetta input sotto forma di:

2
____
__
______
___

su STDIN e fornisce un output simile

________________
____
________________________________________________________________
________

Innanzitutto, il programma importa la Math Library , che ovviamente è interamente scritta in ReRegex. La maggior parte di questo è quindi tre espressioni regolari.

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

Il primo corrisponde alla nostra base di input e cerca una riga unaria dopo di essa. quindi, sostituisce quella linea con ;$1^d<$4>, che è la base, alla potenza dell'Unario (in decimale). La libreria matematica gestisce la conversione di base e l'esponente. A; viene posizionato all'inizio per identificarlo in seguito come finito.

Il secondo, corrisponde alla base, quindi a molte righe di;, prima di terminare. Se questo corrisponde all'intera cosa, si stacca dalla base. lasciandoti solo con le risposte e ;s.

L'ultimo, corrisponde appena unario all'inizio, facoltativamente, quindi una ;risposta. Quindi trasforma di nuovo quella risposta in unaria, senza il ;.

Poiché l'output non corrisponde al primo regex, non esegue il loop all'infinito, quindi la nostra soluzione viene emessa.



2

Röda , 19 byte

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

Provalo online!

Prende un array come input e restituisce un flusso di valori come output.

Spiegazione

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 byte

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

Provalo online!Esempio di utilizzo: f 3 ["##","#","###","#"]ritorna ["#########","###","###########################","###"].

Utilizzare mapM putStrLn $ f 3 ["##","#","###","#"]per ottenere un risultato visivamente più piacevole:

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

Sto solo commentando qui perché non posso commentare il post che hai eliminato ... prova sum[sum[]^sum[],sum[]^sum[]].
Ørjan Johansen,

2

05AB1E , 9 byte

Le barre sono separate da spazi, il carattere di output è uguale al carattere di input.

¬Š#€gm×ðý

Provalo 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 byte

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

Provalo online!


Questo ritorna con una nuova riga iniziale, che non è consentita dalla regex. È possibile utilizzare [str_pad]."\n"invece di "\n".[str_pad]risolvere questo problema (+1 byte). Inoltre, puoi assumere che cos'è il filler, quindi puoi salvare due byte $l[0]cambiandolo in "#".
fireflame241

@ fireflame241 Fatto grazie
Jörg Hülsermann,

1

Gelatina , 7 byte

ṁL*@¥¥€

Un collegamento monadico che prende e restituisce elenchi di barre (essi stessi elenchi di caratteri, stringhe AKA) il carattere di riempimento è flessibile.

Provalo online!(il piè di pagina imposta l'elenco risultante unendo i suoi elementi con le nuove righe.)

Come?

ṁ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 a 7 byte: ṁ"L€*@¥- ottenere la lunghezza di ciascuna barra ( L€), aumentare basea quella potenza ( *@), quindi comprimere ( ") la lista e quella applicare la muffa diade ( ) tra le due.


4 rapidi e 3 collegamenti effettivi? Questa sfida è piuttosto pesante nel controllare il flusso di dati ...
ETHproductions

Sì, potrebbe esserci una soluzione più breve disponibile ...
Jonathan Allan,

@JonathanAllan Temo di no.
Erik the Outgolfer,

@ETHproductions In realtà è un link nel suo insieme. La spiegazione avrebbe potuto essere praticamente solo una riga.
Erik the Outgolfer,

1

Rubino , 29 byte

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

Provalo online!

Sì, ho scoperto la scorsa settimana che ?#produce una stringa di un carattere. Non ho idea del perché questa funzione esista, ma sono sicuro che sia così.


1
L' ?Xoperatore, dove Xè presente un personaggio, è l' operatore "ottieni la rappresentazione predefinita di questo personaggio". In Ruby <1.9, restituirebbe il punto di codice Unicode del carattere, perché è così che sono stati definiti i caratteri, ma ora restituisce una stringa contenente il carattere. Fa parte di un passaggio generale verso una gestione Unicode più coerente in Ruby.
Tutleman,

@Turtleman, c'è un'uva passa isterica per il motivo per cui ?Xviene utilizzata? Molte convenzioni più eccentriche di Ruby, come la pletora di $variabili variabili, esistono a causa della familiarità con Perl.
ymbirtt

1

JavaScript (ES8), 39 byte

Prende la base come numero intero e il grafico come una matrice di stringhe con qualsiasi carattere come riempimento, usando la sintassi del curry.

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

Provalo

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 byte

Questa versione prende il grafico come una stringa separata da nuova riga, sempre con qualsiasi carattere come riempimento.

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

Non pensare di aver bisogno della mbandiera sulla regex, per impostazione predefinita .non corrisponde alle nuove righe.
ETHproductions

Hmm, non so da dove provenga - i pericoli di provare a giocare a golf da un telefono. Grazie per averlo segnalato, @ETHproductions.
Shaggy,

0

Mathematica, 86 byte

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

ingresso

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


ok ... Risolto ......
J42161217

0

Ottava, 42 byte

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

* L'input / output della stringa non corrisponde completamente al regex ma è possibile capire quale barra è quale.

Una funzione prende come base di input be un array 2D di caratteri scontenenti "!"e l'output è anche un array di caratteri.

Provalo online!

Spiegazione:

                       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 byte

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

Formato di input

L'input è richiesto nel seguente formato:

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

0

Carbone , 11 byte

NβWS«PXβLι↓

Provalo online! Il collegamento è alla versione dettagliata del codice. L'I / O è come un elenco di stringhe di -caratteri (si noti che per terminare l'elenco è necessaria una riga vuota).


0

V , 27 byte

L'idea di base è che aggiungiamo a 'a ciascuna riga (n ^ 0), quindi per ogni #sostituiamo la 's nella riga con [input] * '. Alla fine ho scambiato di nuovo tutto 'per#

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

Provalo online!


0

R , 35 byte

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

una funzione anonima che accetta le stringhe come elenco e base e restituisce un elenco di stringhe.

Provalo online!


0

05AB1E , 10 byte

U|v1Xygm×,

Il carattere del filer è 1e il delimitatore è una nuova riga.

Provalo 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 byte

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

;#+;|¶.*$

Provalo online! Dopotutto, un grafico a barre è solo un elenco di numeri unari. Accetta l'input come grafico (usando #s) seguito dalla base in decimale (per evitare confusione). Spiegazione: I primi prefissi di sostituzione 1 e la base per ciascuna riga del grafico. La seconda sostituzione moltiplica quindi il primo numero su ciascuna riga per la seconda, purché il terzo numero sia diverso da zero. La terza sostituzione quindi decrementa il terzo numero su ciascuna riga. Queste due sostituzioni vengono ripetute fino a quando il terzo numero diventa zero. L'ultima sostituzione cancella la base ovunque, lasciando il risultato desiderato.



0

Alice , 23 byte

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

Provalo online!

Non solo non sono una smettitrice, ma sono così impegnata a fare il punto correttamente che uso ! come riempitivo. Ciò attirerà sicuramente l'attenzione del lettore.

Spiegazione

Gli specchi vengono mantenuti in questa spiegazione per renderlo più chiaro quando il programma passa tra le modalità cardinale e ordinale.

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

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

L'elenco delle stringhe di input è nel primo parametro, @^a. Il secondo parametro $^bè la base. Viene restituito un elenco di stringhe di output.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.