로그 스케일은 Quitters를위한 것입니다


24

누구나 로그 스케일이 종료 된 것임을 알고 있습니다. 따라서 베이스가 주어진 로그 스케일로 막대 그래프를 비활성화 하는 프로그램이나 함수를 작성해야합니다 .

막대 그래프 입력은 막대 목록 인 단일 문자열로 가져옵니다. 여기서 로그 스케일 막대 그래프의 각 막대는 선택한 인쇄 가능 (또는 공백) 구분 기호 (0x09-0x0A + 0x20-0x7E)로 구분됩니다. 인쇄 가능한 비 공백 (0x21-0x7E) 필러 문자로 구성됩니다.

프로그램 또는 함수는 막대 목록 인 단일 문자열을 출력합니다. 여기서 각 막대는 입력이 구분 된 것과 동일한 구분 기호로 구분되며 입력이 구성된 것과 동일한 필러 문자로 구성됩니다.

"\ n"(한 줄 바꿈)의 구분 기호와 "#"의 필러 문자를 선택합니다. 프로그램이나 함수에 전달 된 입력은 다음과 같습니다.

기본 = 2 및 문자열 =

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

코드는 막대의 길이가 [4,2,6,3]입니다. 2get [2^4,2^2,2^6,2^3]= 을 기준 으로 각 길이의 안티 로그를 계산합니다 [16,4,64,8]. 그런 다음 길이는 선형 스케일 막대 형식으로 출력됩니다.

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

입출력

귀하의 프로그램이나 기능은 합리적인 형식으로 입력 및 출력 될 수 있습니다 .

입력베이스는 당신은 기본 완전히 정규식 일치에 문자열 입력이 보장 미만 256 가정 5 월 1 일보다 정수 큰 것으로 보장된다 (f+s)+f+, 어디 fs각각 당신의 필러와 구분 기호로 대체됩니다.

문자열 출력은 완전히 정규식 일치해야합니다 (f+s)+f+, f그리고 s각각 같은 필러와 구분 기호로 대체됩니다. 출력에는 선택적으로 후행 줄 바꿈이있을 수 있습니다.

출력 및 입력은 하위 문자열로 구분되는 대신 문자열 목록 일 수도 있지만 어떤 막대가 어떤 막대인지 이해할 수 있어야합니다.

테스트 케이스

(필러는 #구분자가 있다고 가정 \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
-
#
#
##
##
#
##
#
#
#
#
##
##
#
#
##
#
-
##
##
####
####
##
####
##
##
##
##
####
####
##
##
####
##

답변:


6

x86 32 비트 기계 코드 기능, 21 바이트

x86-64 기계 코드 기능, 22 바이트

32 비트 모드에서 1B를 절약하려면 separator = filler-1을 사용해야합니다 (예 : fill=0및) sep=/. 22 바이트 버전은 임의의 구분 기호 및 필러를 사용할 수 있습니다.


이것은 입력 분리기 = \n(0xa), 출력 채우기 기 = 0, 출력 분리기 = /= 필러 -1 이있는 21 바이트 버전 입니다. 이 상수는 쉽게 변경할 수 있습니다.

; 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

64 비트 버전은 2 바이트 DEC 또는를 사용하여 1 바이트 더 깁니다 mov al, output_separator. 그 외에는, 기계 코드는 두 버전에 대해 동일하지만, 일부 레지스터 이름 변경 (예 : rcx대신 ecx에서 pop).

테스트 프로그램 (베이스 3)을 실행 한 샘플 출력 :

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

알고리즘 :

exp *= base모든 필러 문자에 대해 입력을 반복하십시오 . 구분 기호와 종료 0 바이트에서 exp필러 바이트와 구분 기호를 출력 문자열에 추가하고로 재설정하십시오 exp=1. 입력이 줄 바꿈 종결 자로 끝나지 않도록 보장하는 것이 매우 편리합니다 .

입력시 구분 기호 위의 모든 바이트 값 (부호없는 비교)은 필러로 처리되고 구분 기호 아래의 모든 바이트 값은 문자열 끝 마커로 처리됩니다. (0 바이트를 명시 적으로 검사 test al,al하면 내부 루프에 의해 설정된 플래그 에서 추가 대 분기가 필요합니다).


규칙은 후행 줄 바꿈 일 때 후행 구분 기호 만 허용합니다. 내 구현은 항상 구분 기호를 추가합니다. 32 비트 모드에서 1B를 절약하려면 해당 규칙에 구분 기호 = 0xa ( '\n'ASCII LF = 줄 바꿈), 필러 = 0xb ( '\v'ASCII VT = 세로 탭)가 필요합니다. 그것은 인간 친화적이지 않지만 법의 서한을 만족시킵니다. (16 진수 덤프 또는
tr $'\v' x출력이 작동하는지 확인하거나 출력 구분 기호 및 필러를 인쇄 할 수 있도록 상수를 변경 할 수 있습니다. 또한 규칙에 따라 출력에 사용되는 것과 동일한 채우기 / 채우기로 입력을 수락 할 수있는 것으로 나타났습니다 하지만 그 규칙을 어기면 얻을 수있는 것이 없습니다.).


NASM / YASM 소스. %if테스트 프로그램에 포함 된 내용을 사용하여 32 또는 64 비트 코드로 빌드하거나 rcx를 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

이 함수는 시그니처가있는 x86-64 SystemV ABI를 따릅니다.이 함수
void str_exp(char *out /*rdi*/, const char *src /*rsi*/, unsigned base /*edx*/);

는 끝에 마지막 포인터를 남겨 두어 출력 문자열의 길이를 호출자에게만 알려주 므로이rdi 값을 표준 통화 규칙.

xchg eax,edi엔드 포인터를 eax 또는 rax로 반환하는 데 1 또는 2 바이트 ( )의 비용이 듭니다 . (x32 ABI를 사용하는 경우 포인터는 32 비트 만 보장됩니다. 그렇지 않으면 xchg rax,rdi호출자가 낮은 32 비트 외부의 버퍼에 포인터를 전달하는 경우 사용해야 합니다.) 나는 이것을 버전에 포함시키지 않았습니다. 호출자가에서 값을 얻지 않고 사용할 수있는 해결 방법이 있으므로 게시하지 않고 rdiC에서 이것을 호출 할 수 있습니다.

우리는 출력 문자열이나 아무것도 널 종료하지 않으므로 줄 바꿈 만됩니다. 이를 수정하려면 2 바이트가 xchg eax,ecx / stosb 필요 합니다. (rcx는 0에서 0입니다 rep stosb.)

출력 문자열 길이를 찾는 방법은 다음과 같습니다.

  • rdi는 반환 할 때 문자열의 과거 끝을 가리 킵니다 (호출자가 len = end-start를 수행 할 수 있음)
  • 호출자는 입력에 몇 개의 행이 있었는지 알 수 있으며 줄 바꿈을 계산합니다.
  • 호출자는 큰 제로 버퍼를 사용할 수 있습니다 strlen().

그것들은 예쁘거나 효율적이지 않습니다 (asm 호출자의 RDI 반환 값 사용 제외). 원한다면 C에서 golfed asm 함수를 호출하지 마십시오.


크기 / 범위 제한

최대 출력 문자열 크기는 가상 메모리 주소 공간 제한에 의해서만 제한됩니다. (주로 현재 x86-64 하드웨어는 가상 주소에서 48 개의 유효 비트 만 지원하며, 0 확장 대신 부호 확장으로 반으로 나눕니다. 링크 된 답변의 다이어그램을 참조하십시오 .)

32 비트 레지스터에 지수를 축적하기 때문에 각 행은 최대 2 ** 32-1 필러 바이트 만 가질 수 있습니다.

이 함수는 0에서 2 ** 32-1 사이의베이스에 대해 올바르게 작동합니다. (베이스 0에 대한 정정은 0 ^ x = 0입니다. 즉, 필러 바이트가없는 빈 줄입니다.베이스 1에 대한 올바른 값은 항상 1 ^ x = 1이므로 라인 당 1 개의 필러.)

또한 Intel IvyBridge 이상에서 엄청나게 빠릅니다. 특히 정렬 된 메모리에 큰 행이 기록되는 경우에 특히 그렇습니다. ERMSB 기능을 사용하여 CPU에서 정렬 된 포인터를 사용하여 대량으로 rep stosb최적의 구현을 memset()수행합니다 . 예를 들어 180 ** 4는 0.97GB이며 i7-6700k Skylake (~ 256k 소프트 페이지 오류 포함)에서 / dev / null에 쓰려면 0.27 초가 걸립니다. (리눅스에서는 / dev / null 용 장치 드라이버가 아무 데나 데이터를 복사하지 않고 그냥 반환합니다. 따라서 항상 rep stosb메모리를 처음 만질 때 트리거되는 소프트 페이지 오류가 발생합니다. 불행히도 BSS의 배열에 투명한 거대한 페이지를 사용하지 않으면 madvise()시스템 호출로 인해 속도가 빨라질 것입니다.)

테스트 프로그램 :

정적 바이너리를 빌드하고 ./string-exponential $'#\n##\n###' $(seq 2)base 2와 같이 실행하십시오 .를 구현하지 않으려면 atoi을 사용합니다 base = argc-2. (명령 줄 길이 제한으로 엄청나게 큰베이스를 테스트 할 수 없습니다.)

이 랩퍼는 최대 1GB의 출력 문자열에 작동합니다. (거대한 문자열조차도 단일 write () 시스템 호출 만하지 만 Linux는 파이프에 쓰는 경우에도 이것을 지원합니다). 문자를 세 려면 파이프로 들어가 wc -c거나 strace ./foo ... > /dev/nullsyscall 쓰기에 대한 인수를 보는 데 사용 하십시오.

이는 RDI 리턴 값을 활용하여에 대한 문자열 길이를 인수로 계산합니다 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.

이것은 특히 x86 문자열 연산에서 asm에게 아주 잘 어울리는 재미있는 도전이었습니다 . 규칙은 줄 바꿈을 처리하지 않고 입력 문자열 끝에서 종결자를 처리하지 않도록 잘 설계되었습니다.

곱셈이 반복되는 지수는 반복 더하기를 곱하는 것과 같습니다. 어쨌든 각 입력 행의 문자 수를 계산하기 위해 반복해야했습니다.

나는 one-operand mul또는 long imul대신을 사용하는 것을 고려 imul r,r했지만 EAX의 암시 적 사용은 LODSB와 충돌합니다.


또한 load 및 compare 대신 SCASB를 시도했지만 SCASBxchg esi,edi 와 STOSB가 모두 EDI를 사용하기 때문에 내부 루프 전후에 필요했습니다 . 따라서 64 비트 버전은 x32 ABI를 사용해야 64 비트 포인터가 잘리지 않습니다.

STOSB를 피하는 것은 옵션이 아닙니다. 그 밖의 다른 곳은 없습니다. SCASB를 사용할 때의 이점 중 절반은 내부 루프를 떠난 후 AL = filler이므로 REP STOSB에 대한 설정이 필요 없습니다.

SCASB는 내가하고있는 것과 다른 방향으로 비교하므로 비교를 취소해야했습니다.

xchg와 scasb에 대한 나의 최선의 시도. 작동하지만 짧지는 않습니다. ( 32 비트 코드, inc/ dec트릭을 사용하여 필러를 구분 기호로 변경 )

; 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    

의 입력에 ../.../.대해을 생성합니다 ..../......../../. separator = newline으로 버전의 16 진수 덤프를 표시하지 않아도됩니다.


4

Mathematica 41 38 바이트

LLlAMnYP 덕분에 -3 바이트

이것은 문자열리스트와 정수가 뒤 따르는 입력을받습니다. 출력은 또한 문자열 목록입니다.

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

설명:

                   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

이전 버전, 41 바이트

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

"" <> "#"~Table~#는 3 바이트보다 짧으며 "#"~StringRepeat~#아마도 골프를 더 할 수 있습니다.
LLlAMnYP

3

Japt , 7 바이트

그래프를 "필러로, 밑을 정수로하는 문자열 배열로 가져옵니다 .

£QpVpXl

온라인으로 사용해보십시오

}R그래프를 줄 바꿈으로 구분 된 문자열로 사용하려면 끝에 추가하십시오 . ( 시도해보십시오 )


설명

    :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 바이트

Y'iw^1HL(Y"

구분자는 공간입니다. 필러는 공백 이외의 문자입니다.

온라인으로 사용해보십시오!

설명

       % 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

이것은 작동하지 않는 것 같습니다. TIO에 포함 된 테스트 케이스의 출력에서 ​​각 라인의 길이는 9,3,27,9 여야하지만 대신 6,3,9,3이어야합니다.
Shaggy

@Shaggy 당신은 완전히 옳습니다. 알아 주셔서 감사합니다. 최신 편집에서 실수를했습니다. 이전 버전으로 롤백했습니다. ehich가 정확합니다.
Luis Mendo

설명에서 어떻게 작동하는지 알 수 없었습니다. 그런 다음 TIO를 클릭했습니다! : D
얽히고 설킨 Shaggy

1
@Shaggy 방금이 버전에 대한 설명을 추가했습니다.
Luis Mendo

3

하스켈 , 37 33 바이트

sudee 덕분에 4 바이트 감소

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

기술:

\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

실망 스럽게도, 이것은 읽기 어려운 pointfree 버전보다 2 바이트 짧습니다.

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

입력은 단일 문자열이어야합니다
bartavelle

@bartavelle 일 필요는 없습니다.
Shaggy

이것이 내가 이해하는 바입니다. 막대 그래프 입력은 단일 문자열로 간주됩니다 ...
bartavelle

1
@bartavelle : 출력 및 입력은 하위 문자열로 구분되는 대신 문자열 목록 일 수도 있지만 어떤 막대가 어떤 막대인지 이해할 수 있어야합니다.
Julian Wolf

2
당신은 대체 할 수 있습니다 replicate(b^length x)'#''#'<$[1..b^length x].
sudee

3

ReRegex , 105 바이트

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

온라인으로 사용해보십시오!

ReRegex는 Retina의 추악한 사촌과 비슷 하지만 정규 표현식에 모든 노력을 기울이지 않고 멋진 연산자가 아닙니다.

물론, 그것은 또한 가지고 #import#input모두 하드 코딩 입력을 저장하고, 계속해서 또 다시 같은 표현을 재 작성 할 수 있습니다.

설명했다.

다음과 같은 형식으로 입력을받습니다.

2
____
__
______
___

STDIN에서 다음과 같은 출력을 제공합니다.

________________
____
________________________________________________________________
________

먼저, 프로그램은 수학 라이브러리를 가져옵니다. 물론이 라이브러리 는 모두 ReRegex로 작성되었습니다. 이것의 대부분은 세 개의 정규 표현식입니다.

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

첫 번째는 우리의 입력 기반과 일치하고 그 후에 단항 라인을 찾습니다. 그런 다음 해당 행을 ;$1^d<$4>(소수점) 단항의 거듭 제곱으로 밑줄 인으로 바꿉니다 . 수학 라이브러리는 기본 변환과 지수를 처리합니다. A; 나중에 완료된 것으로 식별하기 위해 시작 부분에 배치됩니다.

두 번째는 밑줄과 일치 한 다음 끝나기 전에; 이것이 전체와 일치하면 밑면을 자릅니다. 대답과 ;s로 uf를 떠나십시오 .

마지막은 시작시 단항과 일치하고 선택적으로 ;응답합니다. 그런 다음을 사용하지 않고 해당 답변을 다시 단항으로 변환합니다 ;.

출력은 첫 번째 정규 표현식과 일치하지 않으므로 무한 반복되지 않으므로 솔루션이 출력됩니다.



2

Röda , 19 바이트

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

온라인으로 사용해보십시오!

배열을 입력으로 취하고 값 스트림을 출력으로 리턴합니다.

설명

f n,s{s|["#"*n^#_]}              n is the number and s is the array of strings consisting of #s
      s|                         Push the each value of s to the stream
        [        ]               For each push
         "#"*                     "#" repeated
             n^#_                 n raised to the length of the string

2

하스켈 , 32 바이트

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

온라인으로 사용해보십시오! 사용법 예 : f 3 ["##","#","###","#"]returns ["#########","###","###########################","###"].

mapM putStrLn $ f 3 ["##","#","###","#"]보다 시각적으로 만족스러운 결과를 얻으려면 사용하십시오 .

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

삭제 한 게시물에 댓글을 달 수 없기 때문에 여기에 댓글을 달았습니다 ... 시도해보십시오 sum[sum[]^sum[],sum[]^sum[]].
Ørjan Johansen 2016 년

2

05AB1E , 9 바이트

막대는 공백으로 구분되며 출력 문자는 입력 문자와 동일합니다.

¬Š#€gm×ðý

온라인으로 사용해보십시오!

¬Š#€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 바이트

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

온라인으로 사용해보십시오!


이것은 정규식에서 허용되지 않는 선행 개행과 함께 반환됩니다. 이것을 수정 하는 [str_pad]."\n"대신 사용할 수 있습니다 "\n".[str_pad](+1 바이트). 또한 필러가 무엇인지 가정 할 수 있으므로 $l[0]로 변경하여 2 바이트를 절약 할 수 "#"있습니다.
fireflame241 '

@ fireflame241 감사합니다
Jörg Hülsermann

1

젤리 , 7 바이트

ṁL*@¥¥€

필러 문자는 막대 목록 (문자 목록, AKA 문자열)을 가져오고 반환하는 모나드 링크입니다.

온라인으로 사용해보십시오! 바닥 글은 요소를 줄 바꿈으로 결합하여 결과 목록을 확인합니다.

방법?

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

대안 7 바이 터 : ṁ"L€*@¥-각 막대의 길이 ( L€)를 가져 와서 base그 힘 ( *@)으로 올린 다음 "목록 을 압축 ( ) 하고 두 개 사이에 금형 다이어 드 ( ) 를 적용하십시오 .


4 개의 퀵과 3 개의 실제 링크? 이 과제는 데이터 흐름을 제어하는 ​​데 상당히 무겁습니다 ...
ETHproductions

예, 더 짧은 해결책이있을 수 있습니다 ...
Jonathan Allan

@JonathanAllan 없습니다.
Outgolfer Erik

@ETHproductions 실제로 전체적으로 하나의 링크입니다. 설명은 한 줄에 불과했습니다.
Outgolfer Erik

1

루비 , 29 바이트

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

온라인으로 사용해보십시오!

예, 지난주 ?#에 단일 문자 문자열 을 생성 한다는 것을 알았습니다 . 이 기능이 왜 존재하는지 잘 모르겠지만 기능이 만족 스럽습니다.


1
?X운영자, X일부 문자는 "이 문자의 기본 표현을 얻을"연산자입니다. Ruby <1.9에서는 문자가 정의 된 방식이므로 문자의 유니 코드 코드 포인트를 리턴하지만 문자를 포함하는 문자열을 리턴합니다. Ruby에서보다 일관된 유니 코드 처리를 향한 일반적인 전환의 일부입니다.
Tutleman

@Turtleman, 왜 ?X사용되는 히스테리 건포도 가 있습니까? 많은 변수와 같은 많은 루비의 기발한 규칙 $은 Perl에 익숙하기 때문에 존재합니다.
ymbirtt

1

자바 스크립트 (ES8), 39 바이트

카레 구문을 사용하여 밑을 정수로, 그래프를 임의의 문자를 채울 수있는 문자열 배열로 취합니다.

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

시도 해봐

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>


대안, 49 바이트

이 버전은 그래프를 개행으로 구분 된 문자열로 사용하며, 다시 문자를 필러로 사용합니다.

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

m정규식에 플래그 가 필요하다고 생각하지 마십시오 .. 기본적으로 줄 바꿈과 일치하지 않습니다.
ETHproductions

흠, 그것이 어디에서 왔는지 모릅니다-전화로 골프를 치려고하는 위험. @ETHproductions를 지적 해 주셔서 감사합니다.
Shaggy

0

매스 매 티카, 86 바이트

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

입력

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


ok ... 고정 ......
J42161217

0

옥타브, 42 바이트

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

* 문자열 입력 / 출력이 정규식과 완전히 일치하지는 않지만 어떤 막대가 어떤 것인지 이해할 수 있습니다.

함수는 입력 기준으로 포함 되며 b2D 문자 배열을 s포함 "!"하며 출력도 문자 배열입니다.

온라인으로 사용해보십시오!

설명:

                       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 바이트

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

입력 형식

다음 형식으로 입력해야합니다.

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


0

V , 27 바이트

기본적인 아이디어는 우리가 추가한다는 것입니다 '각 행 (N ^ 0)으로하고 각각에 대해 #우리가 대체 '와 라인들 [input] * '. 끝에서 나는 모든 교환 '을 위해 #다시

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

온라인으로 사용해보십시오!



0

05AB1E , 10 바이트

U|v1Xygm×,

파일러 캐릭터는 1 구분 기호는 줄 바꿈입니다.

온라인으로 사용해보십시오!

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

레티 나 , 62 바이트

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

;#+;|¶.*$

온라인으로 사용해보십시오! 결국 막대 그래프는 단항 숫자의 목록입니다. 입력을 그래프로 사용하고 ( #s를 사용하여 ) 밑을 십진수로 표시합니다 (혼동을 피함). 설명 : 첫 번째 대체 접두어는 1이고 밑줄은 그래프의 각 행입니다. 두 번째 교체는 세 번째 숫자가 0이 아닌 한 각 줄의 첫 번째 숫자에 두 번째 숫자를 곱합니다. 그런 다음 세 번째 교체는 각 줄에서 세 번째 숫자를 줄입니다. 이 두 교체는 세 번째 숫자가 0이 될 때까지 반복됩니다. 마지막 교체는베이스를 모든 곳에서 삭제하고 원하는 결과를 남깁니다.



0

Alice , 23 바이트

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

온라인으로 사용해보십시오!

나는 떨림뿐만 아니라, 내가 사용하는 포인트를 올바르게 만들기 위해 최선을 다하고 있습니다. ! 필러로 있습니다. 그것은 확실히 독자의 관심을 끌 것입니다.

설명

프로그램이 기본 모드와 서수 모드 사이를 전환 할 때 더 명확하게하기 위해이 설명에서 미러가 유지됩니다.

/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

펄 6 , 26 바이트

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

입력 문자열 목록은 첫 번째 매개 변수 인에 @^a있습니다. 두 번째 매개 변수 $^b는 기본입니다. 출력 문자열 목록이 반환됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.