Log-Skalen sind für Drückeberger

24

Jeder weiß, dass Log-Skalen für Drückeberger sind . Aus diesem Grund müssen Sie ein Programm oder eine Funktion schreiben, die ein Balkendiagramm mit einer logarithmischen Skala, die eine Basis hat, deklassiert .

Die Balkendiagrammeingabe wird als einzelne Zeichenfolge verwendet, bei der es sich um eine Liste von Balken handelt, bei der jeder Balken des Balkendiagramms der Protokollskala durch das druckbare (oder Leerzeichen-) Trennzeichen Ihrer Wahl (also 0x09-0x0A + 0x20-0x7E) und getrennt ist Besteht aus einem druckbaren Füllzeichen ohne Leerzeichen (also 0x21-0x7E) Ihrer Wahl.

Das Programm oder die Funktion gibt eine einzelne Zeichenfolge aus, bei der es sich um eine Liste von Balken handelt, wobei jeder Balken durch dasselbe Trennzeichen getrennt ist, durch das die Eingabe getrennt wurde, und aus demselben Füllzeichen besteht, aus dem die Eingabe besteht.

Beispiel

Wir wählen ein Trennzeichen von "\ n" (eine neue Zeile) und ein Füllzeichen von "#". Die Eingabe für unser Programm oder unsere Funktion lautet:

base = 2 und string =

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

Der Code würde feststellen, dass die Längen der Balken sind [4,2,6,3]. Es würde das Anti-Log jeder Länge mit base berechnen 2, um [2^4,2^2,2^6,2^3]= zu erhalten [16,4,64,8]. Dann werden die Längen im linearen Maßstab ausgegeben:

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

Input-Output

Ihr Programm oder Ihre Funktion kann in jedem vernünftigen Format eingegeben und ausgegeben werden .

Es wird garantiert, dass die Eingabebasis eine Ganzzahl größer als 1 ist. Sie können davon ausgehen, dass die Basis kleiner als 256 ist. Die Zeichenfolgeneingabe entspricht garantiert vollständig dem regulären Ausdruck (f+s)+f+, wobei fund sdurch Ihre Füll- bzw. Trennzeichen ersetzt werden.

Die Zeichenfolgenausgabe muss vollständig mit dem regulären Ausdruck übereinstimmen (f+s)+f+, wobei fund sdurch denselben Füll- bzw. Begrenzer ersetzt werden. Die Ausgabe kann optional eine nachgestellte Newline enthalten.

Die Ausgabe und Eingabe kann auch eine Liste von Zeichenfolgen sein, anstatt durch eine Teilzeichenfolge begrenzt zu sein, obwohl es möglich sein muss, zu verstehen, welcher Balken welcher ist.

Testfälle

(Angenommen, Füller ist #und Begrenzer ist \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
-
#
#
##
##
#
##
#
#
#
#
##
##
#
#
##
#
-
##
##
####
####
##
####
##
##
##
##
####
####
##
##
####
##
fireflame241
quelle

Antworten:

6

x86 32-Bit-Maschinencodefunktion, 21 Byte

x86-64-Maschinencodefunktion, 22 Byte

Das Speichern von 1B im 32-Bit-Modus erfordert die Verwendung von separator = filler-1, z . B. fill=0und sep=/. Die 22-Byte-Version kann eine beliebige Auswahl an Trennzeichen und Füllzeichen verwenden.


Dies ist die 21-Byte-Version mit Input-Separator = \n(0xa), Output-Filler = 0, Output-Separator = /= Filler-1. Diese Konstanten können leicht geändert werden.

; 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

Die 64-Bit-Version ist 1 Byte länger und verwendet ein 2-Byte-DEC oder ein mov al, output_separator. Davon abgesehen ist der Maschinencode für beide Versionen gleich, aber einige Registernamen ändern sich (z. B. rcxanstelle von ecxin pop).

Beispielausgabe zum Ausführen des Testprogramms (Basis 3):

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

Algorithmus :

Durchlaufen Sie den Eingang exp *= basefür jedes Füllzeichen. Fügen Sie bei Begrenzern und dem abschließenden Null-Byte Füllbytes expund dann ein Trennzeichen an die Ausgabezeichenfolge an und setzen Sie sie auf zurück exp=1. Es ist sehr praktisch, dass die Eingabe garantiert nicht mit einem Zeilenumbruch und einem Abschlusszeichen endet.

Bei der Eingabe wird jeder Byte-Wert über dem Trennzeichen (vorzeichenloser Vergleich) als Füllzeichen und jeder Byte-Wert unter dem Trennzeichen als Ende-der-Zeichenfolge-Markierung behandelt. (Eine explizite Überprüfung auf ein Null-Byte würde eine zusätzliche oder eine test al,alVerzweigung auf Flags erfordern, die von der inneren Schleife gesetzt werden.)


Die Regeln erlauben nur ein nachfolgendes Trennzeichen, wenn es sich um eine nachfolgende Newline handelt. Meine Implementierung hängt immer das Trennzeichen an. Um die 1B-Speicherung im 32-Bit-Modus zu erhalten, ist für diese Regel das Trennzeichen 0xa ( '\n'ASCII LF = Zeilenvorschub) und das Füllzeichen 0xb ( '\v'ASCII VT = vertikaler Tabulator) erforderlich . Das ist nicht sehr menschenfreundlich, entspricht aber dem Wortlaut des Gesetzes. (Sie können hexdump oder
tr $'\v' xdie Ausgabe, um zu überprüfen, ob es funktioniert, oder ändern Sie die Konstante, damit das Ausgabetrennzeichen und das Füllzeichen gedruckt werden können. Ich habe auch festgestellt, dass die Regeln offenbar erfordern, dass Eingaben mit derselben Füllung / demselben Sep akzeptiert werden, die für die Ausgabe verwendet werden , aber ich sehe keine Vorteile, wenn ich gegen diese Regel verstoße.).


NASM / YASM-Quelle. Erstellen Sie als 32- oder 64-Bit-Code %ifmit dem im Testprogramm enthaltenen Material oder ändern Sie einfach 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

Die Funktion folgt der x86-64-SystemV-ABI mit Signatur.
void str_exp(char *out /*rdi*/, const char *src /*rsi*/, unsigned base /*edx*/);

Sie informiert den Aufrufer nur über die Länge der Ausgabezeichenfolge, indem sie einen Zeiger hinter dem Ende hinterlässt rdi, sodass Sie diesen Wert als Rückgabewert in einer Non- Zeichenfolge betrachten können Standard-Aufrufkonvention.

Es würde 1 oder 2 Bytes kosten ( xchg eax,edi), um den Endzeiger in eax oder rax zurückzugeben. (Wenn Sie das x32-ABI verwenden, sind Zeiger garantiert nur 32-Bit-Zeiger, andernfalls müssen Sie xchg rax,rdiZeiger verwenden, wenn der Aufrufer einen Zeiger an einen Puffer außerhalb der niedrigen 32-Bit-Zeiger übergibt.) Ich habe dies in der aktuellen Version nicht berücksichtigt Posten, weil es Problemumgehungen gibt, die der Aufrufer verwenden kann, ohne den Wert von zu erhalten rdi, sodass Sie dies von C aus ohne Wrapper aufrufen können.

Wir beenden die Ausgabezeichenfolge oder etwas anderes nicht mit Nullen, daher wird sie nur mit Zeilenumbrüchen beendet. Es würde 2 Bytes dauern, um das zu beheben: xchg eax,ecx / stosb (rcx ist null von rep stosb.)

Die Möglichkeiten, die Länge der Ausgabezeichenfolge herauszufinden, sind:

  • rdi zeigt bei der Rückkehr auf das Ende des Strings (damit der Aufrufer len = end-start ausführen kann)
  • Der Anrufer kann nur wissen, wie viele Zeilen sich in der Eingabe befanden, und Zeilenumbrüche zählen
  • Der Anrufer kann einen großen Puffer mit Nullen verwenden und strlen()danach.

Sie sind weder hübsch noch effizient (mit Ausnahme der Verwendung des RDI-Rückgabewerts eines ASM-Aufrufers), aber wenn Sie dies wünschen, rufen Sie die ASM-Funktionen von C.: P nicht auf


Größen- / Bereichsbeschränkungen

Die maximale Größe der Ausgabezeichenfolge ist nur durch die Adressraumbeschränkungen des virtuellen Speichers begrenzt. (Hauptsächlich unterstützt die aktuelle x86-64-Hardware nur 48 signifikante Bits in virtuellen Adressen, die in zwei Hälften geteilt werden, weil sie sich durch Vorzeichen und nicht durch Null verlängern. Siehe das Diagramm in der verknüpften Antwort .)

Jede Zeile kann nur maximal 2 ** 32 - 1 Füllbytes enthalten, da ich die Exponentialfunktion in einem 32-Bit-Register akkumuliere.

Die Funktion funktioniert korrekt für Basen von 0 bis 2 ** 32 - 1. (Richtig für Basis 0 ist 0 ^ x = 0, dh nur leere Zeilen ohne Füllbytes. Richtig für Basis 1 ist 1 ^ x = 1, also immer 1 Füller pro Zeile.)

Es ist auch auf Intel IvyBridge und höher unglaublich schnell, besonders wenn große Zeilen in den ausgerichteten Speicher geschrieben werden. rep stosbist eine optimale Implementierung memset()für große Anzahlen mit ausgerichteten Zeigern auf CPUs mit der ERMSB-Funktion . Beispiel: 180 ** 4 ist 0,97 GB und es dauert 0,27 Sekunden auf meinem i7-6700k Skylake (mit ~ 256k weichen Seitenfehlern), um nach / dev / null zu schreiben. (Unter Linux kopiert der Gerätetreiber für / dev / null die Daten nirgendwo hin, er kehrt nur zurück. Die ganze Zeit befindet sich also im rep stosbund in den weichen Seitenfehlern, die beim ersten Berühren des Speichers auftreten. Es ist.) Leider werden keine transparenten Riesen-Seiten für das Array im BSS verwendet. Wahrscheinlich würde ein madvise()Systemaufruf es beschleunigen.)

Testprogramm :

Erstellen Sie eine statische Binärdatei und führen Sie sie wie ./string-exponential $'#\n##\n###' $(seq 2)für Basis 2 aus. Um die Implementierung einer zu vermeiden, wird eine atoiverwendet base = argc-2. (Befehlszeilenlängenbeschränkungen verhindern das Testen von lächerlich großen Basen.)

Dieser Wrapper funktioniert für Ausgabe-Strings bis zu 1 GB. (Es ruft sogar für gigantische Strings nur ein einziges write () - System auf, aber Linux unterstützt dies sogar für das Schreiben in Pipes). wc -cVerwenden Sie strace ./foo ... > /dev/nullzum Zählen von Zeichen die Pipe in oder , um das Argument für den Write-Syscall anzuzeigen.

Dies nutzt den RDI-Rückgabewert, um die Zeichenfolgenlänge als Argument für zu berechnen 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.

Dies war eine unterhaltsame Herausforderung, die sich besonders für x86-String-Ops sehr gut eignet . Die Regeln sind so konzipiert, dass keine Zeilenumbrüche und keine Abschlusszeichen am Ende der Eingabezeichenfolge verarbeitet werden müssen.

Ein Exponential mit wiederholter Multiplikation ist wie ein Multiplizieren mit wiederholter Addition, und ich musste trotzdem eine Schleife durchlaufen, um die Zeichen in jeder Eingabezeile zu zählen.

Ich habe überlegt, einen muloder einen imullängeren Operanden zu verwenden imul r,r, aber die implizite Verwendung von EAX würde zu einem Konflikt mit LODSB führen.


Ich habe auch SCASB anstelle von Laden und Vergleichen ausprobiert , aber ich brauchte xchg esi,edivor und nach der inneren Schleife, da SCASB und STOSB beide EDI verwenden. (Daher muss die 64-Bit-Version das x32-ABI verwenden, um das Abschneiden von 64-Bit-Zeigern zu vermeiden.)

Das Vermeiden von STOSB ist keine Option. nichts anderes ist annähernd so kurz. Und der halbe Vorteil der Verwendung von SCASB ist, dass AL = Füller nach dem Verlassen der inneren Schleife ist, sodass für REP STOSB kein Setup erforderlich ist.

SCASB vergleicht in die andere Richtung als ich, also musste ich die Vergleiche umkehren.

Mein bester Versuch mit xchg und scasb. Funktioniert, ist aber nicht kürzer. ( 32-Bit-Code, mit dem inc/ dec-Trick Füllzeichen in Trennzeichen ändern ).

; 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    

Für eine Eingabe von ../.../., wird erzeugt ..../......../../. Ich werde nicht die Mühe machen, einen Hexdump der Version mit separator = newline anzuzeigen.

Peter Cordes
quelle
4

Mathematica 41 38 Bytes

-3 Bytes dank LLlAMnYP

Die Eingabe erfolgt als Liste von Zeichenfolgen, gefolgt von einer Ganzzahl. Die Ausgabe ist auch eine Liste von Zeichenfolgen.

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

Erläuterung:

                   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

Alte Version, 41 Bytes

"#"~StringRepeat~#&/@(#2^StringLength@#)&
Ian Miller
quelle
"" <> "#"~Table~#ist 3 Bytes kürzer als "#"~StringRepeat~#, wahrscheinlich auch weiter golfbar.
LLlAMnYP
3

Japt , 7 Bytes

Nimmt das Diagramm als ein Array von Zeichenfolgen mit "als Füllzeichen und die Basis als Ganzzahl.

£QpVpXl

Probieren Sie es online aus

Fügen Sie }Rdas Ende hinzu, um das Diagramm stattdessen als durch Zeilenumbrüche getrennte Zeichenfolge zu verwenden. ( Probieren Sie es aus )


Erläuterung

    :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.
Zottelig
quelle
3

MATL , 14 11 Bytes

Y'iw^1HL(Y"

Trennzeichen ist Raum. Füllzeichen ist jedes andere Zeichen als Leerzeichen.

Probieren Sie es online!

Erläuterung

       % 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
Luis Mendo
quelle
Das scheint nicht zu funktionieren; Die Länge jeder Zeile in der Ausgabe für den Testfall, den Sie in Ihr TIO aufgenommen haben, sollte 9,3,27,9 betragen, stattdessen jedoch 6,3,9,3.
Shaggy
@ Shaggy Du hast vollkommen recht. Danke fürs bemerken. Ich habe in meiner letzten Bearbeitung einen Fehler gemacht. Ich habe auf die vorherige Version zurückgesetzt, ehich ist richtig
Luis Mendo
Konnte nicht aus der Erklärung herausfinden, wie es funktionierte - dann klickte ich mich zum TIO durch! : D
Shaggy
1
@ Shaggy Ich habe gerade eine Erklärung für diese Version hinzugefügt, hoffentlich klarer!
Luis Mendo
3

Haskell , 37 33 Bytes

4 Bytes dank sudee abgeschabt

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

Beschreibung:

\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

Enttäuschenderweise ist dies 2 Bytes kürzer als die weitaus schwerer lesbare pointfree-Version:

map.(flip replicate '#'.).(.length).(^)
Julian Wolf
quelle
Die Eingabe sollte eine einzelne Zeichenfolge sein
Bartavelle
@bartavelle, nicht unbedingt.
Shaggy
Das ist es, was ich unter verstehe. Die Balkendiagrammeingabe wird als einzelne Zeichenfolge verstanden ...
bartavelle
1
@bartavelle: Die Ausgabe und Eingabe kann auch eine Liste von Zeichenfolgen sein, anstatt durch eine Teilzeichenfolge begrenzt zu sein, obwohl es möglich sein muss, zu verstehen, welcher Balken welcher ist.
Julian Wolf
2
Sie können ersetzen replicate(b^length x)'#'mit '#'<$[1..b^length x].
Sonntag,
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

Probieren Sie es online!

ReRegex ist wie Retina hässliche Cousin, der gibt alles , um reguläre Ausdrücke die Mühe, statt seiner eigenen Phantasie Betreiber haben.

Natürlich hat es auch #importund #inputbeide Hardcoding Eingabe zu speichern und neu zu schreiben die gleichen Ausdrücke immer und immer wieder.

Erklärt.

Nimmt Eingaben in Form von:

2
____
__
______
___

auf STDIN und gibt Ausgabe wie

________________
____
________________________________________________________________
________

Erstens importiert das Programm die Mathematikbibliothek , die natürlich vollständig in ReRegex geschrieben ist. Der Großteil davon sind dann drei reguläre Ausdrücke.

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

Der erste stimmt mit unserer Eingabebasis überein und sucht danach eine unäre Zeile. es ersetzt dann diese Zeile mit ;$1^d<$4>, die die Basis ist, nach der Potenz von (In Decimal) Unary. Die Math-Bibliothek verwaltet die Basisumwandlung und den Exponenten. EIN ; wird am Anfang platziert, um es später als fertig zu identifizieren.

Das zweite entspricht der Basis, dann vielen Zeilen von;, bevor es endet. Wenn dies mit der gesamten Sache übereinstimmt, wird die Basis abgeschnitten. Lass uf mit nur den Antworten und ;s.

Der letzte, der zu Beginn nur unärgerlich übereinstimmt, gibt optional dann eine ;Antwort. Dann wandelt es diese Antwort wieder in eine unäre um, ohne die ;.

Da die Ausgabe nicht mit dem ersten regulären Ausdruck übereinstimmt, wird keine Endlosschleife ausgeführt, sodass unsere Lösung ausgegeben wird.

Ein Taco
quelle
2

Python 2 , 52 36 Bytes

Eingabe und Ausgabe werden als Arrays von Zeichenfolgen verwendet. #ist der Füllstoff.

lambda s,n:['#'*n**len(l)for l in s]

Probieren Sie es online!

total menschlich
quelle
2

Röda , 19 Bytes

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

Probieren Sie es online!

Nimmt ein Array als Eingabe und gibt einen Strom von Werten als Ausgabe zurück.

Erläuterung

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
Kritixi Lithos
quelle
2

Haskell , 32 Bytes

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

Probieren Sie es online! Anwendungsbeispiel: f 3 ["##","#","###","#"]Rückgabe ["#########","###","###########################","###"].

Verwenden Sie mapM putStrLn $ f 3 ["##","#","###","#"]diese Option , um eine optisch ansprechendere Ausgabe zu erzielen:

#########
###
###########################
###
Laikoni
quelle
Einfach hier kommentieren, da ich den gelöschten Beitrag nicht kommentieren kann ... versuchen Sie es sum[sum[]^sum[],sum[]^sum[]].
Ørjan Johansen
2

05AB1E , 9 Bytes

Balken werden durch Leerzeichen getrennt, das Ausgabezeichen entspricht dem Eingabezeichen.

¬Š#€gm×ðý

Probieren Sie es 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
kalsowerus
quelle
1

PHP, 69 Bytes

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

Probieren Sie es online!

Jörg Hülsermann
quelle
Dies wird mit einer führenden Zeile zurückgegeben, die vom regulären Ausdruck nicht zugelassen wird. Sie können [str_pad]."\n"statt verwenden "\n".[str_pad], um dies zu beheben (+1 Byte). Sie können auch davon ausgehen, dass es sich bei dem Füllzeichen um ein Füllzeichen handelt, sodass Sie zwei Bytes einsparen können, $l[0]indem Sie es in ändern "#".
fireflame241
@ fireflame241 Fertig Danke
Jörg
1

Gelee , 7 Bytes

ṁL*@¥¥€

Eine monadische Verknüpfung, die Listen der Balken (selbst Listen von Zeichen, AKA-Zeichenfolgen) aufnimmt und zurückgibt, macht das Füllzeichen flexibel.

Probieren Sie es online!(Die Fußzeile verschönert die resultierende Liste, indem sie ihre Elemente mit Zeilenumbrüchen verbindet.)

Wie?

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

Alternative 7-Byte-Methode: ṁ"L€*@¥- Länge der einzelnen Balken ermitteln ( L€), baseauf diese Potenz erhöhen ( *@), dann "die Liste zippen ( ) und die Form-Dyade ( ) zwischen den beiden anwenden .

Jonathan Allan
quelle
4 Quicks und 3 aktuelle Links? Diese Herausforderung ist für die Kontrolle des Datenflusses ziemlich
groß
Ja, möglicherweise ist eine kürzere Lösung verfügbar ...
Jonathan Allan
@ JonathanAllan Ich fürchte, es gibt keine.
Erik der Outgolfer
@ETHproductions Es ist eigentlich ein Link als Ganzes. Die Erklärung hätte so ziemlich nur eine Zeile sein können.
Erik der Outgolfer
1

Ruby , 29 Bytes

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

Probieren Sie es online!

Ja, ich habe letzte Woche herausgefunden, dass es sich um ?#eine Zeichenfolge mit nur einem Buchstaben handelt. Ich habe keine Ahnung, warum diese Funktion existiert, bin aber sicher froh, dass sie existiert.

ymbirtt
quelle
1
Der ?XOperator, bei dem Xes sich um ein Zeichen handelt, ist der Operator "Die Standarddarstellung dieses Zeichens abrufen". In Ruby <1.9 wird der Unicode-Codepunkt des Zeichens zurückgegeben, da die Zeichen so definiert wurden. Jetzt wird jedoch eine Zeichenfolge zurückgegeben, die das Zeichen enthält. Dies ist Teil eines allgemeinen Wandels hin zu einer konsistenteren Unicode-Verarbeitung in Ruby.
Tutleman
@Turtleman, gibt es eine hysterische Rosine, warum ?Xwird sie verwendet? Viele schrulligere Konventionen von Ruby, wie die Vielzahl von $Variablen, existieren aufgrund der Vertrautheit mit Perl.
ymbirtt
1

JavaScript (ES8), 39 Byte

Nimmt die Basis als Ganzzahl und das Diagramm als Array von Zeichenfolgen mit einem beliebigen Zeichen als Füllzeichen und verwendet dabei die aktuelle Syntax.

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

Versuch es

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>


Alternative 49 Bytes

In dieser Version wird das Diagramm als durch Zeilenumbrüche getrennte Zeichenfolge mit einem beliebigen Zeichen als Füllzeichen verwendet.

b=>s=>s.replace(/.+/g,m=>m.padEnd(b**m.length,m))
Zottelig
quelle
Denken Sie nicht, dass Sie die mFlagge auf dem .regulären Ausdruck benötigen , da diese standardmäßig nicht mit Zeilenumbrüchen übereinstimmt.
ETHproductions
Hmm, ich weiß nicht, woher das kommt - die Gefahren, von einem Telefon aus Golf zu spielen. Vielen Dank für den Hinweis, @ETHproductions.
Shaggy
0

Mathematica, 86 Bytes

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

Eingang

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

J42161217
quelle
ok ...
Behoben
0

Oktave, 42 Bytes

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

* Die Eingabe / Ausgabe der Zeichenfolge stimmt nicht vollständig mit dem regulären Ausdruck überein, es ist jedoch möglich zu verstehen, welcher Balken welcher ist.

Eine Funktion verwendet als Eingabebasis bein 2D-Array von Zeichen s, "!"das Zeichen enthält, und die Ausgabe ist auch ein Array von Zeichen.

Probieren Sie es online!

Erläuterung:

                       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.
rahnema1
quelle
0

CJam, 20 Bytes

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

Eingabeformat

Die Eingabe muss im folgenden Format erfolgen:

"##
####
######"2
Roman Gräf
quelle
0

Holzkohle , 11 Bytes

NβWS«PXβLι↓

Probieren Sie es online! Link ist eine ausführliche Version des Codes. E / A ist eine Liste von Zeichenfolgen -(beachten Sie, dass Sie eine leere Zeile benötigen, um die Liste zu beenden).

Neil
quelle
0

V , 27 Bytes

Die Grundidee ist, dass wir 'jeder Zeile ein a hinzufügen (n ^ 0) und dann für jede Zeile #das 's in der Zeile mit ersetzen [input] * '. Am Ende tauschte ich alle die 'für #wieder

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

Probieren Sie es online!

nmjcman101
quelle
0

R , 35 Bytes

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

Eine anonyme Funktion, die die Zeichenfolgen als Liste und Basis verwendet und eine Liste von Zeichenfolgen zurückgibt.

Probieren Sie es online!

Giuseppe
quelle
0

05AB1E , 10 Bytes

U|v1Xygm×,

Das Filer-Zeichen ist 1und das Trennzeichen ist ein Zeilenumbruch.

Probieren Sie es 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
Riley
quelle
0

Netzhaut , 62 Bytes

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

;#+;|¶.*$

Probieren Sie es online! Ein Balkendiagramm ist schließlich nur eine Liste von unären Zahlen. Übernimmt die Eingabe als Diagramm (mit #s), gefolgt von der Dezimalbasis (um Verwirrung zu vermeiden). Erläuterung: Das erste Ersetzungspräfix 1 und die Basis werden in jede Zeile des Diagramms eingefügt. Die zweite Ersetzung multipliziert dann die erste Zahl in jeder Zeile mit der zweiten, solange die dritte Zahl ungleich Null ist. Die dritte Ersetzung dekrementiert dann die dritte Nummer in jeder Zeile. Diese beiden Ersetzungen werden wiederholt, bis die dritte Zahl Null wird. Der letzte Ersatz löscht die Basis überall und hinterlässt das gewünschte Ergebnis.

Neil
quelle
0

Alice , 23 Bytes

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

Probieren Sie es online!

Ich bin nicht nur kein Quitter, sondern ich bin auch so entschlossen, den Punkt, den ich benutze, richtig zu formulieren ! als Füllstoff verwende. Das wird die Aufmerksamkeit des Lesers auf sich ziehen.

Erläuterung

In dieser Erklärung werden Spiegel beibehalten, um das Umschalten zwischen dem Kardinal- und dem Ordinalmodus zu verdeutlichen.

/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)
Nitrodon
quelle
0

Perl 6 , 26 Bytes

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

Die Liste der Eingabezeichenfolgen befindet sich im ersten Parameter @^a. Der zweite Parameter $^bist die Basis. Eine Liste der Ausgabezeichenfolgen wird zurückgegeben.

Sean
quelle