เครื่องชั่ง Log สำหรับ Quitters


24

ทุกคนรู้ว่าเครื่องชั่งบันทึกมีการเลิกสูบ ดังนั้นคุณต้องเขียนโปรแกรมหรือฟังก์ชั่นที่ยกเลิกการออกกราฟแท่งที่มีสเกลบันทึกที่กำหนดให้เป็นฐาน

อินพุตกราฟแท่งถูกนำมาเป็นสตริงเดี่ยวซึ่งเป็นรายการของแท่งซึ่งแต่ละแท่งกราฟกราฟมาตราส่วนบันทึกถูกคั่นด้วยตัวคั่นที่พิมพ์ได้ (หรือช่องว่าง) ที่คุณเลือก (ดังนั้น 0x09-0x0A + 0x20-0x7E) และ ประกอบด้วยฟิลเลอร์ที่ไม่สามารถพิมพ์ได้ (เช่นดังนั้น 0x21-0x7E) ที่คุณเลือก

โปรแกรมหรือฟังก์ชั่นเอาท์พุทสตริงเดียวซึ่งเป็นรายการของบาร์ที่แต่ละบาร์จะถูกคั่นด้วยตัวคั่นเดียวกันอินพุตถูกคั่นด้วยและประกอบด้วยอักขระตัวเติมเดียวที่อินพุตประกอบด้วย

ตัวอย่าง

เราเลือกตัวคั่นของ "\ n" (หนึ่งบรรทัดใหม่) และอักขระตัวเติมของ "#" อินพุตที่ส่งผ่านไปยังโปรแกรมหรือฟังก์ชันของเราคือ:

base = 2 และ string =

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

[4,2,6,3]รหัสจะพบว่าความยาวของบาร์ที่มี มันจะคำนวณการป้องกันการเข้าสู่ระบบของแต่ละความยาวที่มีฐาน2ที่จะได้รับ=[2^4,2^2,2^6,2^3] [16,4,64,8]จากนั้นความยาวจะถูกส่งออกในรูปแบบแท่งขนาดเชิงเส้น:

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

อินพุต / เอาต์พุต

โปรแกรมหรือฟังก์ชั่นอาจเข้าและส่งออกของคุณในรูปแบบที่เหมาะสม

ฐานอินพุตมีการรับประกันว่าจะเป็นจำนวนเต็มมากกว่า 1 คุณอาจถือว่าฐานเป็นน้อยกว่า 256 อินพุตสตริงรับประกันว่าจะตรงกับ regex (f+s)+f+ที่fและsจะถูกแทนที่ด้วยฟิลเลอร์และตัวคั่นของคุณตามลำดับ

เอาต์พุตสตริงต้องตรงกับ regex (f+s)+f+โดยที่fและsจะถูกแทนที่ด้วยฟิลเลอร์และตัวคั่นเดียวกันตามลำดับ เอาต์พุตอาจมีทางเลือกขึ้นบรรทัดใหม่

เอาต์พุตและอินพุตอาจเป็นรายการของสตริงแทนที่จะคั่นด้วยซับสตริงแม้ว่าจะต้องเป็นไปได้ที่จะเข้าใจว่าแถบใดอยู่

Testcases

(สมมติว่าฟิลเลอร์เป็น#และตัวคั่นคือ\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 ต้องใช้คั่น = ฟิลเลอร์-1 เช่นและfill=0 sep=/เวอร์ชัน 22 ไบต์สามารถใช้ตัวเลือกตัวคั่นและฟิลเลอร์โดยพลการ


นี่คือรุ่น 21- ไบต์พร้อมอินพุต - ตัวคั่น = \n(0xa), เอาท์พุทฟิลเลอร์ = 0, เอาท์พุท - ตัวคั่น = /= filler-1 ค่าคงที่เหล่านี้สามารถเปลี่ยนแปลงได้ง่าย

; 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 บิตเป็น 1 ไบต์อีกต่อไปโดยใช้ 2 mov al, output_separatorไบต์ธันวาคมหรือ นอกเหนือจากนั้นรหัสเครื่องจะเหมือนกันสำหรับทั้งสองเวอร์ชัน แต่ชื่อทะเบียนบางรายการเปลี่ยนไป (เช่นrcxแทนที่จะเป็นecxในpop)

เอาต์พุตตัวอย่างจากการรันโปรแกรมทดสอบ (ฐาน 3):

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

อัลกอริทึม :

วนรอบอินพุตให้ทำexp *= baseเพื่อตัวกรองทุกตัว เมื่อวันที่คั่นและไบต์ยุติศูนย์ผนวกไบต์ของฟิลเลอร์แล้วคั่นสตริงการส่งออกและการตั้งค่าไปexp exp=1สะดวกมากที่จะรับประกันว่าอินพุตจะไม่จบด้วยทั้ง newline และ terminator

ในอินพุตค่าไบต์ใด ๆ ที่อยู่เหนือตัวแยก (การเปรียบเทียบที่ไม่ได้ลงชื่อ) จะถือว่าเป็นฟิลเลอร์และค่าไบต์ใด ๆ ที่อยู่ด้านล่างตัวคั่นจะถือว่าเป็นตัวทำเครื่องหมายสิ้นสุดสตริง (การตรวจสอบอย่างชัดเจนสำหรับศูนย์ไบต์จะใช้การtest al,alเปรียบเทียบกับการแตกแขนงบนแฟล็กที่กำหนดโดยลูปภายใน)


กฎอนุญาตเฉพาะตัวคั่นต่อท้ายเมื่อเป็นบรรทัดใหม่ต่อท้าย การใช้งานของฉันผนวกตัวคั่นเสมอ ในการรับการประหยัด 1B ในโหมด 32 บิตกฎนั้นต้องการตัวคั่น = 0xa ( '\n'ASCII LF = linefeed), ฟิลเลอร์ = 0xb ( '\v'แท็บ ASCII VT = แนวตั้ง) นั่นไม่ได้เป็นมิตรกับมนุษย์ แต่เป็นไปตามตัวอักษรของกฎหมาย (คุณสามารถ hexdump หรือ
tr $'\v' xเอาท์พุทเพื่อตรวจสอบว่ามันทำงานหรือเปลี่ยนค่าคงที่ดังนั้นเอาท์พุทตัวคั่นและฟิลเลอร์ที่พิมพ์ได้ฉันยังสังเกตเห็นว่ากฎดูเหมือนจะต้องการให้มันสามารถรับอินพุตด้วยการเติม / sep เดียวกัน แต่ฉันไม่เห็นอะไรเลยที่จะได้รับจากการละเมิดกฎนั้น)


แหล่ง NASM / YASM สร้างเป็นรหัส 32 หรือ 64 บิตโดยใช้%ifสิ่งต่าง ๆ ที่รวมอยู่ในโปรแกรมทดสอบหรือเปลี่ยน 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ดังนั้นคุณสามารถพิจารณาค่าตอบแทนในรูปแบบที่ไม่ใช่ แบบแผนการโทรมาตรฐาน

มันจะมีราคา 1 หรือ 2 ไบต์ ( xchg eax,edi) เพื่อส่งคืนตัวชี้ปลายทางใน eax หรือ rax (ถ้าใช้ x32 ABI พอยน์เตอร์จะรับประกันได้เพียง 32 บิตมิฉะนั้นเราจะต้องใช้xchg rax,rdiในกรณีที่ผู้เรียกส่งตัวชี้ไปยังบัฟเฟอร์นอก 32 บิตต่ำ) ฉันไม่ได้รวมสิ่งนี้ไว้ในรุ่นที่ฉันใช้ การโพสต์เนื่องจากมีวิธีแก้ปัญหาที่ผู้โทรสามารถใช้ได้โดยไม่ได้รับค่าrdiดังนั้นคุณจึงสามารถเรียกสิ่งนี้ได้จาก C โดยไม่มี wrapper

เราไม่ได้ยกเลิก null output string หรืออะไรเลยดังนั้นมันจึงขึ้นบรรทัดใหม่เท่านั้น จะใช้เวลา 2 ไบต์เพื่อแก้ไขว่า: xchg eax,ecx / stosb (rcx เป็นศูนย์จากrep stosb)

วิธีในการหาความยาวของเอาต์พุต - สตริงคือ

  • rdi ชี้ไปที่หนึ่งในอดีตของสตริงเมื่อส่งคืน (ดังนั้นผู้เรียกสามารถทำ len = end-start)
  • ผู้โทรสามารถรู้ได้ว่ามีกี่แถวในอินพุตและนับบรรทัดใหม่
  • ผู้เรียกสามารถใช้บัฟเฟอร์ศูนย์ขนาดใหญ่และstrlen()หลังจากนั้น

พวกมันไม่ได้สวยหรือมีประสิทธิภาพ (ยกเว้นการใช้ค่าส่งคืน RDI จาก asm caller) แต่ถ้าคุณต้องการที่จะไม่เรียกฟังก์ชั่น asm จาก golfed C. : P


ข้อ จำกัด ด้านขนาด / ช่วง

ขนาดสตริงเอาต์พุตสูงสุดถูก จำกัด โดยข้อ จำกัด พื้นที่ที่อยู่หน่วยความจำเสมือนเท่านั้น (ส่วนใหญ่ว่าฮาร์ดแวร์ x86-64 ปัจจุบันรองรับเฉพาะบิตที่สำคัญ 48 บิตในที่อยู่เสมือนแบ่งครึ่งเนื่องจากพวกเขาลงชื่อเข้าใช้ขยายแทนการขยายศูนย์ดูแผนภาพในคำตอบที่เชื่อมโยง )

แต่ละแถวสามารถมีขนาดฟิลเลอร์ได้สูงสุด 2 ** 32 - 1 เท่านั้นเนื่องจากฉันสะสมเลขชี้กำลังในการลงทะเบียนแบบ 32 บิต

ฟังก์ชั่นทำงานได้อย่างถูกต้องสำหรับฐานตั้งแต่ 0 ถึง 2 ** 32 - 1 (ถูกต้องสำหรับฐาน 0 คือ 0 ^ x = 0 นั่นคือเพียงบรรทัดว่างที่ไม่มีไบต์ฟิลเลอร์แก้ไขสำหรับฐาน 1 คือ 1 ^ x = 1 เสมอ 1 ฟิลเลอร์ต่อบรรทัด)

นอกจากนี้ยังรวดเร็วอย่างเห็นได้ชัดบน Intel IvyBridge และต่อมาโดยเฉพาะอย่างยิ่งสำหรับแถวขนาดใหญ่ที่ถูกเขียนไปยังหน่วยความจำที่จัดตำแหน่ง rep stosbคือการดำเนินการที่ดีที่สุดของmemset()สำหรับการนับจำนวนขนาดใหญ่ที่มีตัวชี้จัดตำแหน่งบนซีพียูกับคุณลักษณะ ERMSB เช่น 180 ** 4 คือ 0.97GB และใช้เวลา 0.27 วินาทีกับ i7-6700k Skylake ของฉัน (ด้วยความผิดพลาดหน้าซอฟท์เพจ ~ 256k) เพื่อเขียนถึง / dev / null (บน Linux ไดรเวอร์อุปกรณ์สำหรับ / dev / null ไม่ได้คัดลอกข้อมูลทุกที่มันจะกลับมาดังนั้นตลอดเวลาที่อยู่ในrep stosbและข้อผิดพลาดหน้าอ่อนที่เรียกเมื่อสัมผัสหน่วยความจำเป็นครั้งแรกมัน น่าเสียดายที่ไม่ได้ใช้ hugepages แบบโปร่งใสสำหรับอาเรย์ใน BSS อาจเป็นไปได้madvise()ว่าการเรียกของระบบจะเพิ่มความเร็วขึ้น)

โปรแกรมทดสอบ :

สร้างไบนารีแบบคงที่และการทำงานเป็น./string-exponential $'#\n##\n###' $(seq 2)ฐาน 2. เพื่อหลีกเลี่ยงการดำเนินการจะใช้atoi base = argc-2(ขีดจำกัดความยาวบรรทัดคำสั่งป้องกันการทดสอบฐานขนาดใหญ่ที่น่าขัน)

wrapper นี้ใช้งานได้กับสตริงเอาต์พุตสูงสุด 1 GB (มันทำให้การเขียนเพียงครั้งเดียว () การเรียกระบบแม้สำหรับสตริงขนาดใหญ่ แต่ Linux ก็สนับสนุนสิ่งนี้แม้กระทั่งการเขียนไปยังไพพ์) สำหรับการนับอักขระให้ไพพ์เข้าwc -cหรือใช้strace ./foo ... > /dev/nullเพื่อดู arg เพื่อเขียน syscall

นี้ใช้ประโยชน์ของ 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.

นี้เป็นความท้าทายที่สนุกที่ยืมตัวเองเป็นอย่างดีเพื่อ asm โดยเฉพาะอย่างยิ่ง x86 Ops กฎได้รับการออกแบบมาเป็นอย่างดีเพื่อหลีกเลี่ยงการจัดการกับการขึ้นบรรทัดใหม่แล้วตัวยุติที่จุดสิ้นสุดของอินพุตสตริง

เลขชี้กำลังที่มีการคูณซ้ำ ๆ ก็เหมือนกับการคูณด้วยการเพิ่มซ้ำและฉันต้องวนซ้ำเพื่อนับตัวอักษรในแต่ละแถวอินพุต

ฉันพิจารณาว่าใช้ตัวถูกดำเนินการหนึ่งตัวmulหรือimulนานกว่าimul r,rนั้น แต่การใช้ EAX โดยนัยจะขัดแย้งกับ LODSB


ฉันยังลอง SCASB แทนการโหลดและเปรียบเทียบแต่ฉันต้องการxchg esi,ediก่อนและหลังลูปด้านในเนื่องจาก SCASB และ 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


4

Mathematica 41 38 ไบต์

-3 ไบต์ขอบคุณ LLlAMnYP

สิ่งนี้รับอินพุตเป็นรายการของสตริงตามด้วยจำนวนเต็ม เอาต์พุตยังเป็นรายการสตริง

""<>"#"~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

Japtap , 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 คุณพูดถูก ขอบคุณที่สังเกต ฉันทำผิดพลาดในการแก้ไขล่าสุดของฉัน ฉันย้อนกลับไปเป็นเวอร์ชั่นก่อนหน้านี้ถูกต้องแล้ว
Luis Mendo

ไม่สามารถทราบได้ว่ามันทำงานอย่างไรจากคำอธิบาย - จากนั้นฉันคลิกไปที่ TIO! : D
Shaggy

1
@Shaggy ฉันเพิ่งเพิ่มคำอธิบายสำหรับรุ่นนี้หวังว่าชัดเจนขึ้น!
Luis Mendo

3

Haskell , 37 33 ไบต์

4 ไบต์ถูกโกนทิ้งขอบคุณ sudee

\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

น่าผิดหวังนี่คือ2 ไบต์ที่สั้นกว่ารุ่น pointfree ที่อ่านยาก:

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 และให้เอาต์พุตเหมือน

________________
____
________________________________________________________________
________

ประการแรกโปรแกรมนำเข้าMath Libraryซึ่งแน่นอนว่าทั้งหมดเขียนใน ReRegex ส่วนใหญ่ของนี่คือสามนิพจน์ปกติ

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

ครั้งแรกที่ตรงกับฐานข้อมูลของเราและหาเส้น unary หลังจากนั้น จากนั้นจะแทนที่บรรทัดนั้นด้วย;$1^d<$4>ซึ่งเป็นฐานไปสู่พลังของ Unary (เป็นทศนิยม) ห้องสมุดคณิตศาสตร์จัดการการแปลงฐานและเลขชี้กำลัง A; ถูกวางไว้ที่จุดเริ่มต้นเพื่อระบุในภายหลังว่าเสร็จแล้ว

ที่สองตรงกับฐานจากนั้นหลายบรรทัดก่อนจบ หากสิ่งนี้ตรงกับทุกสิ่งมันจะหลุดออกจากฐาน ทิ้ง uf ด้วยคำตอบและ;s เท่านั้น

สุดท้ายจับคู่เพียง unary ที่เริ่มเลือกหรือ;คำตอบ ;จากนั้นก็เปลี่ยนคำตอบลงในเอกนั้นอีกครั้งโดยไม่ต้อง

เนื่องจากผลลัพธ์ไม่ตรงกับ regex แรกจึงไม่วนซ้ำไม่สิ้นสุดดังนั้นโซลูชันของเราจึงแสดงผลออกมา



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

Haskell , 32 ไบต์

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

ลองออนไลน์! ตัวอย่างการใช้งาน: ผลตอบแทนf 3 ["##","#","###","#"]["#########","###","###########################","###"]

ใช้mapM putStrLn $ f 3 ["##","#","###","#"]เพื่อให้ได้ผลลัพธ์ที่ถูกใจยิ่งขึ้น:

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

เพียงแค่แสดงความคิดเห็นที่นี่เพราะฉันไม่สามารถแสดงความคิดเห็นในโพสต์ที่คุณลบ ... sum[sum[]^sum[],sum[]^sum[]]ลอง
Ørjan Johansen

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

ลองออนไลน์!


สิ่งนี้จะส่งคืนด้วยการขึ้นบรรทัดใหม่นำหน้าซึ่งไม่ได้รับอนุญาตจาก regex คุณสามารถใช้[str_pad]."\n"แทน"\n".[str_pad]การแก้ไขปัญหานี้ (+1 ไบต์) นอกจากนี้คุณอาจคิดว่าสิ่งที่ฟิลเลอร์คือเพื่อให้คุณสามารถบันทึกสองไบต์ในโดยเปลี่ยนไป$l[0] "#"
fireflame241

@ fireflame241 เสร็จสิ้นขอบคุณ
JörgHülsermann

1

เยลลี่ขนาด 7 ไบต์

ṁL*@¥¥€

ลิงก์ monadic ที่รับและส่งคืนรายการของแถบ (รายการตัวอักษรของตัวเอง, สตริง AKA) อักขระฟิลเลอร์มีความยืดหยุ่น

ลองออนไลน์!(ส่วนท้าย prettifies รายการผลลัพธ์โดยการเข้าร่วมองค์ประกอบกับ newlines.)

อย่างไร?

ṁ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-byter: ṁ"L€*@¥- รับความยาวของแต่ละแท่ง ( L€), ยกระดับbaseพลังนั้น ( *@), จากนั้น zip ( ") รายการและที่ใช้แม่พิมพ์ dyad ( ) ระหว่างทั้งสอง


4 Quicks และ 3 ลิงค์จริง? ความท้าทายนี้ค่อนข้างหนักในการควบคุมการไหลของข้อมูล ...
ผลิตภัณฑ์ ETH

ใช่อาจจะมีวิธีแก้ปัญหาที่สั้นกว่านี้ ...
Jonathan Allan

@JanathanAllan ฉันกลัวว่าจะไม่มี
Erik the Outgolfer

@ETHproductions จริงๆแล้วมันเป็นลิงค์เดียว คำอธิบายน่าจะเป็นเพียงหนึ่งบรรทัด
Erik the Outgolfer

1

Ruby , 29 ไบต์

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

ลองออนไลน์!

ใช่ฉันค้นพบเมื่อสัปดาห์ที่แล้วซึ่ง?#สร้างสตริงอักขระเดี่ยว ฉันไม่รู้เลยว่าทำไมคุณสมบัตินี้ถึงมีอยู่ แต่ฉันก็ดีใจที่ได้ทำ


1
?Xผู้ประกอบการที่Xเป็นตัวละครบางคนเป็น "ได้รับการแสดงเริ่มต้นของตัวละครตัวนี้" ผู้ประกอบการ ใน Ruby <1.9 มันจะส่งคืนจุดโค้ด Unicode ของตัวละครเพราะนั่นเป็นวิธีการกำหนดตัวอักษร แต่ตอนนี้มันจะส่งกลับสตริงที่มีตัวละคร มันเป็นส่วนหนึ่งของการเปลี่ยนแปลงทั่วไปต่อการจัดการ Unicode ที่สอดคล้องกันมากขึ้นใน Ruby
Tutleman

@ Turtleman มีลูกเกดตีโพยตีพายเพราะเหตุใดจึง?Xใช้ การประชุมที่แปลกประหลาดมากมายของ Ruby เช่นความ$แปรปรวนของตัวแปรมีอยู่เนื่องจากความคุ้นเคยกับ Perl
ymbirtt

1

JavaScript (ES8), 39 ไบต์

ใช้ฐานเป็นจำนวนเต็มและกราฟเป็นอาร์เรย์ของสตริงที่มีอักขระใด ๆ เป็นฟิลเลอร์โดยใช้ไวยากรณ์การ curating

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ตั้งค่าสถานะบน regex โดยค่าเริ่มต้น.ไม่ตรงกับบรรทัดใหม่
ETHproductions

อืมไม่รู้ว่ามาจากไหน - ภัยจากการพยายามเล่นกอล์ฟจากโทรศัพท์ ขอบคุณสำหรับการชี้ให้เห็น @ETHproductions
Shaggy

0

Mathematica, 86 ไบต์

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

อินพุต

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


ตกลง ... แก้ไข ......
J42161217

0

อ็อกเทฟ 42 ไบต์

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

* อินพุต / เอาต์พุตสตริงไม่ตรงกับ regex ทั้งหมด แต่เป็นไปได้ที่จะเข้าใจว่าแถบใดอยู่

ฟังก์ชั่นใช้เป็นฐานอินพุตbและอาร์เรย์ 2D ของตัวอักษร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

ถ่าน 11 ไบต์

NβWS«PXβLι↓

ลองออนไลน์! การเชื่อมโยงคือการสร้างรหัสเวอร์ชัน I / O เป็นรายการของสตริง-อักขระ (โปรดทราบว่าคุณต้องมีบรรทัดว่างเพื่อยกเลิกรายการ)


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

อลิซ 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

Perl 6 , 26 ไบต์

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

รายการสตริงการป้อนข้อมูลอยู่ในพารามิเตอร์แรก, @^a. พารามิเตอร์ที่สอง$^bคือฐาน รายการสตริงเอาต์พุตจะถูกส่งคืน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.