Skale dziennika są dla Quitterów

24

Wszyscy wiedzą, że skale dziennika są przeznaczone do rezygnacji . Dlatego musisz napisać program lub funkcję, która odsuwa wykres słupkowy ze skalą logarytmiczną podaną jako podstawa.

Wejście wykresu słupkowego jest traktowane jako pojedynczy ciąg, który jest listą słupków, przy czym każdy słupek wykresu słupkowego skali logów jest oddzielony ogranicznikiem do drukowania (lub białych spacji) według własnego wyboru (czyli 0x09-0x0A + 0x20-0x7E) i składa się z wybranego przez użytkownika wypełniacza innego niż spacje (czyli 0x21-0x7E).

Program lub funkcja wyprowadza pojedynczy ciąg znaków, który jest listą słupków, przy czym każdy słupek jest oddzielony tym samym ogranicznikiem, od którego wejście zostało oddzielone i składa się z tego samego znaku wypełniającego, z którego składało się wejście.

Przykład

Wybieramy ogranicznik „\ n” (jedna nowa linia) i znak wypełniający „#”. Dane wejściowe przekazywane do naszego programu lub funkcji to:

base = 2 i string =

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

Kod stwierdziłby, że długości pasków są [4,2,6,3]. Obliczałby antylog dla każdej długości z bazą, 2aby uzyskać [2^4,2^2,2^6,2^3]= [16,4,64,8]. Następnie długości są wyprowadzane w formacie liniowego paska podziałki:

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

Wejście wyjście

Twój program lub funkcja może wprowadzać i wyprowadzać w dowolnym rozsądnym formacie .

Podstawa wejściowa ma gwarantowaną liczbę całkowitą większą niż 1. Możesz założyć, że podstawa jest mniejsza niż 256. Gwarantowana wartość wejściowa ciągu znaków jest w pełni zgodna z wyrażeniem regularnym (f+s)+f+, gdzie fi ssą zastępowane odpowiednio wypełniaczem i separatorem.

Dane wyjściowe ciągu muszą w pełni pasować do wyrażenia regularnego (f+s)+f+, gdzie fi ssą zastępowane odpowiednio tym samym wypełniaczem i separatorem. Wyjście może opcjonalnie mieć końcowy znak nowej linii.

Dane wyjściowe i wejściowe mogą być również listą ciągów zamiast ograniczonych przez podłańcuch, chociaż musi być możliwe zrozumienie, który pasek jest który.

Przypadki testowe

(zakładając, że wypełniaczem jest, #a separatorem jest \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
źródło

Odpowiedzi:

6

x86 32-bitowa funkcja kodu maszynowego, 21 bajtów

x86-64 funkcja kodu maszynowego, 22 bajty

Oszczędność trybie 32-bitowym 1B wymaga stosowania separatora = wypełniacza-1, np fill=0i sep=/. Wersja 22-bajtowa może korzystać z dowolnego wyboru separatora i wypełniacza.


To jest wersja 21-bajtowa z separatorem wejściowym = \n(0xa), separatorem wyjściowym = 0, separatorem wyjściowym = /= wypełniaczem-1. Stałe te można łatwo zmienić.

; 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

Wersja 64-bitowa jest dłuższa o 1 bajt, przy użyciu 2-bajtowej DEC lub a mov al, output_separator. Poza tym kod maszynowy jest taki sam dla obu wersji, ale niektóre nazwy rejestrów zmieniają się (np. rcxZamiast ecxw pop).

Przykładowe dane wyjściowe z uruchomienia programu testowego (podstawa 3):

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

Algorytm :

Zapętlaj dane wejściowe, wykonując exp *= basedla każdego znaku wypełniającego. Na ogranicznikach i kończącym bajcie zerowym dołącz expbajty wypełniacza, a następnie separator do ciągu wyjściowego i zresetuj do exp=1. Bardzo wygodnie jest zagwarantować, że wejście nie kończy się zarówno znakiem nowej linii, jak i terminatorem.

Na wejściu każda wartość bajtu powyżej separatora (porównanie bez znaku) jest traktowana jako wypełniacz, a każda wartość bajtu poniżej separatora jest traktowana jako znacznik końca łańcucha. (Bezpośrednie sprawdzenie zerowego bajtu wymagałoby dodatkowego test al,alvs. rozgałęzienia flag ustawionych przez wewnętrzną pętlę).


Reguły zezwalają na separator końcowy tylko wtedy, gdy jest to końcowy znak nowej linii. Moja implementacja zawsze dołącza separator. Aby uzyskać oszczędność 1B w trybie 32-bitowym, ta reguła wymaga separatora = 0xa ( '\n'ASCII LF = podawanie linii), wypełniacz = 0xb ( '\v'ASCII VT = karta pionowa). Nie jest to zbyt przyjazne dla człowieka, ale spełnia literę prawa. (Możesz wykonać zrzut heksowy lub
tr $'\v' xdane wyjściowe, aby sprawdzić, czy to działa, lub zmienić stałą, aby separator wyjściowy i wypełniacz można było wydrukować. Zauważyłem również, że reguły wymagają, aby akceptował dane wejściowe z tym samym wypełnieniem / sep, którego używa dla danych wyjściowych , ale nie widzę nic do zyskania po złamaniu tej zasady).


Źródło NASM / YASM. Zbuduj jako kod 32- lub 64-bitowy, używając %ifrzeczy zawartych w programie testowym lub po prostu zmień rcx na 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

Funkcja podąża za ABV SystemV x86-64, z podpisem.
void str_exp(char *out /*rdi*/, const char *src /*rsi*/, unsigned base /*edx*/);

Informuje dzwoniącego o długości łańcucha wyjściowego, pozostawiając w nim wskaźnik „jeden za końcem” rdi, aby można było uznać to za wartość zwracaną -standardowa konwencja połączeń.

xchg eax,ediZwrócenie wskaźnika końcowego w eax lub rax kosztowałoby 1 lub 2 bajty ( ). (W przypadku korzystania z ABI x32, wskaźniki mają gwarantowane tylko 32 bity, w przeciwnym razie musimy użyć, xchg rax,rdijeśli dzwoniący przekaże wskaźnik do bufora poza małymi 32 bitami.) Nie uwzględniłem tego w wersji Jestem wysyłanie, ponieważ istnieją obejścia, z których osoba dzwoniąca może korzystać bez uzyskiwania wartości rdi, dzięki czemu można wywoływać to z C bez opakowania.

Nie kończymy nawet łańcucha wyjściowego ani nic takiego, więc jest on tylko zakończony znakiem nowej linii. Zajmie to 2 bajty, aby to naprawić: xchg eax,ecx / stosb (rcx wynosi zero od rep stosb.)

Sposoby sprawdzenia długości ciągu wyjściowego są następujące:

  • rdi po powrocie wskazuje jeden-koniec końca łańcucha (więc wywołujący może zrobić len = end-start)
  • dzwoniący może po prostu wiedzieć, ile wierszy było na wejściu i liczyć nowe linie
  • dzwoniący może użyć dużego zerowanego bufora i strlen()później.

Nie są ładne ani wydajne (z wyjątkiem używania wartości zwracanej RDI od wywołującego asm), ale jeśli chcesz, nie wywołuj funkcji asm w golfa z C.: P


Ograniczenia wielkości / zakresu

Maksymalny rozmiar ciągu wyjściowego jest ograniczony tylko ograniczeniami przestrzeni adresowej pamięci wirtualnej. (Głównie, że obecny sprzęt x86-64 obsługuje tylko 48 znaczących bitów w adresach wirtualnych, podzielonych na pół, ponieważ rozszerzają znak zamiast rozszerzania zera. Zobacz diagram w powiązanej odpowiedzi .)

Każdy wiersz może mieć maksymalnie 2 ** 32-1 bajtów wypełniających, ponieważ kumuluję wykładniczy w rejestrze 32-bitowym.

Funkcja działa poprawnie dla baz od 0 do 2 ** 32 - 1. (Prawidłowe dla podstawy 0 to 0 ^ x = 0, tzn. Tylko puste linie bez bajtów wypełniających. Prawidłowe dla podstawy 1 to 1 ^ x = 1, więc zawsze 1 wypełniacz na linię.)

Jest także niesamowicie szybki na Intel IvyBridge i nowszych, szczególnie w przypadku dużych wierszy zapisywanych w wyrównanej pamięci. rep stosbjest optymalną implementacją memset()dla dużej liczby z wyrównanymi wskaźnikami na procesorach z funkcją ERMSB . np. 180 ** 4 to 0,97 GB i zajmuje 0,27 sekundy na moim i7-6700k Skylake (z ~ 256k miękkimi błędami strony), aby zapisać do / dev / null. (W Linuksie sterownik urządzenia dla / dev / null nigdzie nie kopiuje danych, po prostu wraca. Więc cały czas jest w nim rep stosbi błędy strony, które uruchamiają się po dotknięciu pamięci po raz pierwszy. niestety nie używa przezroczystych stronicowania dla tablicy w BSS. Prawdopodobnie madvise()wywołanie systemowe przyspieszy to.)

Program testowy :

Zbuduj statyczny plik binarny i uruchom go jak ./string-exponential $'#\n##\n###' $(seq 2)w bazie 2. Aby uniknąć implementacji atoi, używa base = argc-2. (Ograniczenia długości wiersza poleceń uniemożliwiają testowanie absurdalnie dużych baz.)

To opakowanie działa dla ciągów wyjściowych do 1 GB. (Wykonuje tylko jedno wywołanie systemowe write () nawet dla gigantycznych ciągów, ale Linux obsługuje to nawet przy zapisie do potoków). Aby zliczyć znaki, potokuj do wc -club używaj, strace ./foo ... > /dev/nullaby zobaczyć argument do syscall zapisu.

Wykorzystuje to wartość zwracaną przez RDI do obliczania długości łańcucha jako argumentu dla 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.

Było to zabawne wyzwanie, które bardzo dobrze nadawało się do asm, zwłaszcza operacji na łańcuchach x86 . Reguły są ładnie zaprojektowane, aby uniknąć konieczności obsługi nowej linii, a następnie terminatora na końcu ciągu wejściowego.

Wykładniczy z powtarzanym mnożeniem jest jak mnożenie z powtarzanym dodawaniem, i tak musiałem zapętlić się, aby policzyć znaki w każdym wierszu wejściowym.

Zastanawiałem się nad użyciem jednego argumentu mullub imulzamiast dłuższego imul r,r, ale jego niejawne użycie EAX byłoby sprzeczne z LODSB.


Próbowałem także SCASB zamiast ładować i porównywać , ale potrzebowałem xchg esi,ediprzed i po wewnętrznej pętli, ponieważ zarówno SCASB, jak i STOSB używają EDI. (Więc wersja 64-bitowa musi korzystać z ABI x32, aby uniknąć obcięcia wskaźników 64-bitowych).

Unikanie STOSB nie jest opcją; nic innego nie jest tak krótkie. Połowa korzyści z używania SCASB polega na tym, że AL = wypełniacz po opuszczeniu pętli wewnętrznej, więc nie potrzebujemy żadnej konfiguracji dla REP STOSB.

SCASB porównuje w innym kierunku niż to, co robiłem, więc musiałem odwrócić porównania.

Moja najlepsza próba z xchg i scasb. Działa, ale nie jest krótszy. ( Kod 32-bitowy, użycie inc/ dectrick do zmiany wypełniacza na separator ).

; 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    

Na wejście ../.../.produkuje ..../......../../. Nie zamierzam zawracać sobie głowy wyświetlaniem zrzutu heksadecymalnego z separatorem = nowy wiersz.

Peter Cordes
źródło
4

Mathematica 41 38 bajtów

-3 Bajty dzięki LLlAMnYP

Pobiera to dane wejściowe jako listę ciągów znaków, po których następuje liczba całkowita. Dane wyjściowe to także lista ciągów znaków.

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

Wyjaśnienie:

                   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

Stara wersja, 41 bajtów

"#"~StringRepeat~#&/@(#2^StringLength@#)&
Ian Miller
źródło
"" <> "#"~Table~#jest o 3 bajty krótszy niż "#"~StringRepeat~#, prawdopodobnie także do gry w golfa.
LLlAMnYP,
3

Japt , 7 bajtów

Bierze wykres jako tablicę ciągów z "wypełniaczem, a podstawa jako liczbę całkowitą.

£QpVpXl

Wypróbuj online

Dodaj }Rna końcu, aby zamiast tego wziąć wykres jako ciąg oddzielony znakiem nowej linii. ( Wypróbuj )


Wyjaśnienie

    :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.
Kudłaty
źródło
3

MATL , 14 11 bajtów

Y'iw^1HL(Y"

Ogranicznikiem jest spacja. Wypełniacz to dowolna postać inna niż spacja.

Wypróbuj online!

Wyjaśnienie

       % 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
źródło
To nie wydaje się działać; długość każdego wiersza na wyjściu dla przypadku testowego, który zawarłeś w TIO, powinna wynosić 9,3,27,9, ale zamiast tego wynosi 6,3,9,3.
Kudłaty
@Shaggy Masz całkowitą rację. Dzięki za zauważenie. Popełniłem błąd w mojej ostatniej edycji. Cofnąłem się do poprzedniej wersji, co jest poprawne
Luis Mendo
Z wyjaśnienia nie mogłem zrozumieć, jak to działa - wtedy kliknąłem TIO! : D
Kudłaty
1
@Shaggy Właśnie dodałem wyjaśnienie dla tej wersji, miejmy nadzieję, że jaśniejsze!
Luis Mendo
3

Haskell , 37 33 bajtów

4 bajty ogolone dzięki sudee

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

Opis:

\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

Rozczarowujące jest to, że jest to 2 bajty znacznie krótsze niż trudniejsza do odczytania wersja wolna od punktów:

map.(flip replicate '#'.).(.length).(^)
Julian Wolf
źródło
Dane wejściowe powinny być pojedynczym ciągiem
bartavelle
@bartavelle, niekoniecznie.
Kudłaty
To, co rozumiem przez Wejście wykresu słupkowego jest traktowane jako pojedynczy ciąg ...
bartavelle
1
@bartavelle: Dane wyjściowe i wejściowe mogą być również listą ciągów zamiast ograniczonych przez podłańcuch, chociaż musi być możliwe zrozumienie, który pasek jest który.
Julian Wolf
2
Można wymienić replicate(b^length x)'#'z '#'<$[1..b^length x].
sudee
3

ReRegex , 105 bajtów

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

Wypróbuj online!

ReRegex jest jak brzydki kuzyn Retiny, który wkłada wszystkie wysiłki w wyrażenia regularne, zamiast mieć własne wymyślne operatory.

Oczywiście, ma także #importi #inputdo zapisania zarówno wejścia na stałe, jak i ponownego zapisywania tych samych wyrażeń w kółko.

Wyjaśnił.

Pobiera dane wejściowe w postaci:

2
____
__
______
___

na STDIN i daje wynik jak

________________
____
________________________________________________________________
________

Po pierwsze, program importuje bibliotekę matematyczną , która oczywiście jest w całości napisana w ReRegex. Większość z nich to trzy wyrażenia regularne.

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

Pierwszy pasuje do naszej bazy danych wejściowych i po niej szuka linii jednoargumentowej. następnie zastępuje tę linię ;$1^d<$4>, która jest podstawą, do potęgi Unary (In Decimal). Biblioteka Math obsługuje podstawową konwersję i wykładnik potęgi. A; jest umieszczony na początku, aby zidentyfikować go później jako ukończony.

Drugi, dopasowuje podstawę, a następnie wiele wierszy;, przed zakończeniem. Jeśli to pasuje do całości, odcina się od podstawy. pozostawiając uf tylko odpowiedzi i ;s.

Ostatni, pasuje tylko raz na początku, opcjonalnie, a następnie ;odpowiedź. Następnie ponownie przekształca tę odpowiedź w jednoargumentową, bez ;.

Ponieważ wynik nie pasuje do pierwszego wyrażenia regularnego, nie zapętla się w nieskończoność, więc nasze rozwiązanie jest generowane.

ATaco
źródło
2

Python 2 , 52 36 bajtów

Wejścia i wyjścia są traktowane jako tablice ciągów. #jest wypełniaczem.

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

Wypróbuj online!

całkowicie ludzki
źródło
2

Röda , 19 bajtów

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

Wypróbuj online!

Pobiera tablicę jako dane wejściowe i zwraca strumień wartości jako dane wyjściowe.

Wyjaśnienie

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
źródło
2

Haskell , 32 bajty

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

Wypróbuj online! Przykładowe użycie: f 3 ["##","#","###","#"]zwraca ["#########","###","###########################","###"].

Użyj, mapM putStrLn $ f 3 ["##","#","###","#"]aby uzyskać bardziej przyjemny efekt wizualny:

#########
###
###########################
###
Laikoni
źródło
Po prostu komentuję tutaj, ponieważ nie mogę komentować usuniętego wpisu ... spróbuj sum[sum[]^sum[],sum[]^sum[]].
Ørjan Johansen
2

05AB1E , 9 bajtów

Słupki są oddzielone spacjami, znak wyjściowy jest taki sam jak znak wejściowy.

¬Š#€gm×ðý

Wypróbuj 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
źródło
1

PHP, 69 bajtów

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

Wypróbuj online!

Jörg Hülsermann
źródło
Zwraca wiodący nowy wiersz, który nie jest dozwolony przez wyrażenie regularne. Możesz użyć [str_pad]."\n"zamiast tego "\n".[str_pad]naprawić (+1 bajt). Możesz także założyć, co to jest wypełniacz, więc możesz zapisać dwa bajty $l[0], zmieniając go na "#".
fireflame241
@ fireflame241 Gotowe dziękuję
Jörg Hülsermann
1

Galaretka , 7 bajtów

ṁL*@¥¥€

Monadyczny link pobierający i zwracający listy pasków (same listy znaków, ciągi znaków AKA) znak wypełniający jest elastyczny.

Wypróbuj online! (stopka uwydatnia wynikową listę, łącząc jej elementy z nowymi liniami).

W jaki sposób?

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

Alternatywny 7-bajtowy: ṁ"L€*@¥- uzyskaj długość każdego słupka ( L€), podnieś basedo tej potęgi ( *@), a następnie zip ( ") listę i zastosuj dyadę formy ( ) między nimi.

Jonathan Allan
źródło
4 szybkie i 3 rzeczywiste linki? Wyzwanie to jest dość trudne do kontrolowania przepływu danych ...
ETHprodukcje
Tak, może być dostępne krótsze rozwiązanie ...
Jonathan Allan
@JonathanAllan Obawiam się, że nie ma.
Erik the Outgolfer
@ETHproductions To właściwie jeden link jako całość. Wyjaśnienie mogło być tylko jedną linią.
Erik the Outgolfer,
1

Rubinowy , 29 bajtów

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

Wypróbuj online!

Tak, dowiedziałem się w zeszłym tygodniu, że ?#produkuje ciąg jednoznakowy. Nie mam pojęcia, dlaczego ta funkcja istnieje, ale jestem pewien, że tak jest.

ymbirtt
źródło
1
?XOperator, gdzie Xjest jakaś postać, jest „dostać domyślną reprezentację tego znaku” operator. W Ruby <1.9 zwróci punkt kodowy Unicode znaku, ponieważ tak zdefiniowano znaki, ale teraz zwraca ciąg zawierający znak. Jest to część ogólnego przejścia w kierunku bardziej spójnej obsługi Unicode w Rubim.
Tutleman
@Turtleman, czy jest jakaś histeryczna rodzynka do tego, dlaczego ?Xjest używana? Wiele dziwacznych konwencji Ruby, takich jak mnóstwo $zmiennych, istnieje z powodu znajomości Perla.
ymbirtt
1

JavaScript (ES8), 39 bajtów

Bierze bazę jako liczbę całkowitą, a wykres jako tablicę ciągów z dowolnym znakiem jako wypełniaczem, używając składni curry.

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

Spróbuj

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>


Alternatywnie, 49 bajtów

Ta wersja przyjmuje wykres jako ciąg oddzielony znakiem nowej linii, ponownie z dowolnym znakiem jako wypełniaczem.

b=>s=>s.replace(/.+/g,m=>m.padEnd(b**m.length,m))
Kudłaty
źródło
Nie sądzę, że potrzebujesz mflagi na wyrażeniu regularnym, domyślnie .nie pasuje do nowej linii.
ETHprodukcje
Hmm, nie wiem skąd to się wzięło - niebezpieczeństwa gry w golfa z telefonu. Dziękujemy za zwrócenie uwagi na @ETHproductions.
Kudłaty
0

Mathematica, 86 bajtów

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

wkład

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

J42161217
źródło
ok ... Naprawiono ......
J42161217
0

Oktawa, 42 bajty

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

* Ciąg wejściowy / wyjściowy nie jest w pełni zgodny z wyrażeniem regularnym, ale można zrozumieć, który pasek jest który.

Funkcja przyjmuje jako podstawę wejściową bi tablicę 2D szawierającą znaki, "!"a dane wyjściowe są również tablicą znaków.

Wypróbuj online!

Wyjaśnienie:

                       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
źródło
0

CJam, 20 bajtów

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

Format wejściowy

Dane wejściowe są wymagane w następującym formacie:

"##
####
######"2
Roman Gräf
źródło
0

Węgiel drzewny , 11 bajtów

NβWS«PXβLι↓

Wypróbuj online! Link jest do pełnej wersji kodu. I / O jest jak lista ciągów -znaków (pamiętaj, że potrzebujesz pustej linii, aby zakończyć listę).

Neil
źródło
0

V , 27 bajtów

Podstawową ideą jest to, że dodajemy a 'do każdego wiersza (n ^ 0), a następnie dla każdego #zastępujemy 's w wierszu [input] * '. Pod koniec zamieniłem wszystkie wymienione 'na #raz

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

Wypróbuj online!

nmjcman101
źródło
0

R , 35 bajtów

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

anonimowa funkcja, która bierze łańcuchy jako listę i bazę i zwraca listę łańcuchów.

Wypróbuj online!

Giuseppe
źródło
0

05AB1E , 10 bajtów

U|v1Xygm×,

Znakiem filtru jest, 1a separatorem jest nowa linia.

Wypróbuj 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
źródło
0

Siatkówka , 62 bajty

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

;#+;|¶.*$

Wypróbuj online! W końcu wykres słupkowy to tylko lista liczb jednoargumentowych. Pobiera dane wejściowe jako wykres (za pomocą #s), po którym następuje zasada dziesiętna (aby uniknąć pomyłek). Objaśnienie: Pierwsze zastępcze prefiksy 1 i podstawa do każdej linii wykresu. Druga zamiana mnoży następnie pierwszą liczbę w każdej linii przez drugą, o ile trzecia liczba jest niezerowa. Trzeci zamiennik następnie zmniejsza trzeci numer w każdej linii. Te dwie zamiany są powtarzane, aż trzecia liczba stanie się zero. Ostatnia zamiana usuwa bazę wszędzie, pozostawiając pożądany wynik.

Neil
źródło
0

Alice , 23 bajty

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

Wypróbuj online!

Nie tylko nie poddaję się, ale jestem tak zaangażowany w odpowiednie robienie tego, że używam go !jako wypełniacza. To z pewnością przyciągnie uwagę czytelnika.

Wyjaśnienie

Lustra są zachowane w tym objaśnieniu, aby było bardziej jasne, gdy program przełącza się między trybami kardynalnymi i porządkowymi.

/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
źródło
0

Perl 6 , 26 bajtów

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

Lista ciągów wejściowych jest w pierwszym parametrze @^a. Drugi parametr $^bto podstawa. Zwracana jest lista ciągów wyjściowych.

Sean
źródło