ASCII art uncompression จากหมายเลข base-n


24

นี้เป็นแรงบันดาลใจจากคำตอบ 05AB1Eโดยเมจิก octupus โกศ

รับสองข้อโต้แย้งเป็นจำนวนเต็มบวกและสตริง / รายการของตัวละคร:

  1. แปลตัวเลขเป็น base-n โดยที่ n คือความยาวของสตริง
  2. สำหรับอักขระแต่ละตัวให้แทนที่ทุกลักษณะที่ปรากฏของดัชนีของอักขระนั้นในหมายเลข base-n ด้วยอักขระนั้น
  3. พิมพ์หรือส่งคืนสตริงใหม่

ตัวอย่าง:

Input:
2740, ["|","_"]
2740 -> 101010110100 in base 2
     -> Replace 0s with "|" and 1s with "_"
Output: _|_|_|__|_||

Input:
698911, ["c","h","a","o"]
698911 ->  2222220133 in base 4
       ->  Replace 0s with "c", 1s with "h", 2s with "a", and 3s with "o"
Output -> "aaaaaachoo"

Input:
1928149325670647244912100789213626616560861130859431492905908574660758972167966, [" ","\n","|","_","-"]
Output:
    __   __    
   |  |_|  |   
___|       |___
-   -   -   -  
 - - - - - - - 
- - - - - - - -
_______________

Input: 3446503265645381015412, [':', '\n', '.', '_', '=', ' ', ')', '(', ',']
Output:
_===_
(.,.)
( : )
( : )

กฎ:

  • IO ยืดหยุ่นได้
    • คุณสามารถใช้ตัวเลขในฐานใดก็ได้ตราบใดที่มันสอดคล้องกันระหว่างอินพุต
    • รายการของตัวละครจะต้องเป็นดัชนี 0 ซึ่งโดยที่ 0 คืออักขระตัวแรกและ n-1 เป็นตัวสุดท้าย
  • อักขระที่เป็นไปได้สามารถเป็น ASCII ที่พิมพ์ได้พร้อมกับช่องว่างเช่นแท็บและการขึ้นบรรทัดใหม่
  • รายการที่กำหนดของตัวละครจะมีความยาวอยู่ในช่วงที่2-10ครบวงจร นั่นคือฐานที่เล็กที่สุดคือไบนารีและที่ใหญ่ที่สุดคือทศนิยม ( ไม่มีตัวอักษรที่น่ารำคาญที่นี่ )
  • ช่องโหว่มาตรฐานเป็นสิ่งต้องห้าม
  • รู้สึกอิสระที่จะตอบแม้ว่าภาษาของคุณไม่สามารถจัดการกับกรณีทดสอบขนาดใหญ่

เช่นนี้เป็นรหัสที่สั้นที่สุดสำหรับแต่ละภาษาชนะ ( ฉันรู้ว่าทุกภาษาที่คุณเล่นกอล์ฟมีหนึ่งไบท์อินพร้อมที่จะไป )


Sandbox (ลบแล้ว)
Jo King

3
ฉันรู้สึกเป็นเกียรติมาก 05AB1E ascii-artเป็นที่โปรดปรานของฉันสักครู่
Magic Octopus Urn

คุณสามารถสร้างความท้าทายใหม่: พบการเปลี่ยนแปลงของตัวละครในอาร์เรย์เพื่อลดจำนวน :)
Mazzy

คำตอบ:


8

05AB1E , 7 6 ไบต์

gв¹sèJ

เนื่องจากได้รับแรงบันดาลใจจากคำตอบ 05AB1E คำตอบที่ให้ใน 05AB1E จึงเหมาะสม :)

-1 ไบต์ขอบคุณ@Enigmaโดยการลบ foreach และทำสิ่งนี้โดยปริยาย

ลองมันออนไลน์หรือตรวจสอบกรณีทดสอบทั้งหมด

คำอธิบาย:

g         # `l`: Take the length of the first (string) input
 в        # And then take the second input in base `l`
          # For each digit `y` of this base-converted number:
  ¹sè     #  Push the `y`'th character of the first input
     J    # Join everything together (and output implicitly)

1
gв¹sèJเพื่อบันทึกไบต์
Emigna

@Emigna ขอบคุณ ไม่อยากเชื่อเลยว่า¹sèตอนนี้ฉันไม่ได้คิดถึงตัวเองแล้ว (ฉันรู้ว่าการเปลี่ยน?เป็น a Jจะให้ผลลัพธ์ที่เหมือนกันในกรณีนี้)
Kevin Cruijssen

6

Java 8, 72 50 ไบต์

a->n->n.toString(a.length).chars().map(c->a[c-48])

-22 ไบต์ขอบคุณ@ OlivierGrégoireโดยส่งคืนIntStreamแทนที่จะพิมพ์โดยตรง

ลองมันออนไลน์

คำอธิบาย:

a->n->                  // Method with char-array and BigInteger parameters
  n.toString(a.length)  //  Convert the input-number to Base `amount_of_characters`
   .chars()             //  Loop over it's digits (as characters)
   .map(c->a[c          //   Convert each character to the `i`'th character of the input
              -48])     //   by first converting the digit-character to index-integer `i`

2
a->n->n.toString(a.length).chars().map(c->a[c-48])(50 bytes) ตั้งแต่ "IO is elastic"
Olivier Grégoire

String f(char[]a,int n){return n>0?f(a,n/a.length)+a[n%a.length]:"";}(69 ไบต์) แบบเรียกซ้ำเพื่อความสนุก
Olivier Grégoire

6

Python 3 , 49 ไบต์

ยังไม่สามารถแสดงความคิดเห็นดังนั้นฉันโพสต์คำตอบของ Python 2 ที่ปรับให้เหมาะกับ Python 3.5

f=lambda n,s:n and f(n//len(s),s)+s[n%len(s)]or''

2
ยินดีต้อนรับสู่ PPCG! อย่าลังเลที่จะรวมลิงค์ TIOเพื่อช่วยแสดงวิธีแก้ปัญหาของคุณ
Jo King

5

Japtap, 2 ไบต์

สามารถรับอินพุตที่สองเป็นอาร์เรย์หรือสตริง ล้มเหลวในการทดสอบ 2 กรณีล่าสุดเนื่องจากจำนวนเกินจำนวนเต็มสูงสุดของ JavaScript แทนที่sด้วยìเพื่อส่งออกอาร์เรย์ของตัวละครแทน

sV

ลองมัน


5

Haskell , 40 39 ไบต์

0!_=[]
n!l=cycle l!!n:div n(length l)!l

ลองออนไลน์!

เนื่องจากIntประเภทของ Haskell ถูก จำกัด ไว้9223372036854775807สิ่งนี้จึงล้มเหลวในจำนวนที่มากขึ้น

-1 ขอบคุณไบต์Laikoni

Ungolfed

(!) :: Int -> [Char] -> [Char]

0 ! _ = []  -- If the number is 0, we reached the end. Base case: empty string
n ! l = 
  let newN = (n `div` length l) in   -- divide n by the base
    cycle l!!n                       -- return the char encoded by the LSD ... 
    : newN!l                         -- ... prepended to the rest of the output (computed recursively)

ลองออนไลน์!


ความคิดที่ดีที่จะใช้cycleแทนmod! div n(length l)บันทึกเป็นไบต์
Laikoni

4

MATL , 2 ไบต์

YA

ลองออนไลน์!

อินพุตเป็นตัวเลขและสตริง

ล้มเหลวสำหรับตัวเลขที่เกิน2^53เนื่องจากความแม่นยำจุดลอย

คำอธิบาย

สิ่งที่ต้องYAรู้คือบิวอิน (การแปลงฐานพร้อมสัญลักษณ์เป้าหมายที่ระบุ)


4

JavaScript (ES6), 48 ไบต์

รับอินพุตในรูปแบบ currying (c)(n)โดยที่cคือรายการอักขระและnเป็นจำนวนเต็ม

ปลอดภัยสำหรับn <2 53เท่านั้น

c=>n=>n.toString(c.length).replace(/./g,i=>c[i])

ลองออนไลน์!


JavaScript (ES6), 99 ไบต์

ด้วยการสนับสนุนสำหรับจำนวนเต็มขนาดใหญ่

รับอินพุตในรูปแบบ currying (c)(a)โดยที่cคือรายการอักขระและaคือรายการของเลขทศนิยม (เป็นจำนวนเต็ม)

c=>g=(a,p=0,b=c.length,r=0)=>1/a[p]?g(a.map((d,i)=>(r=d+r*10,d=r/b|0,r%=b,d|i-p||p++,d)),p)+c[r]:''

ลองออนไลน์!


4

x86 รหัสเครื่อง 32 บิต (จำนวนเต็ม 32 บิต): 17 ไบต์

(ดูรุ่นอื่น ๆ ด้านล่างรวมถึง 16 ไบต์สำหรับ 32- บิตหรือ 64- บิตโดยใช้การประชุมที่เรียกว่า DF = 1)

ผู้เรียกผ่าน args ในการลงทะเบียนรวมถึงตัวชี้ไปยังจุดสิ้นสุดของบัฟเฟอร์ส่งออก (เช่นคำตอบ C ของฉัน ; ดูมันสำหรับเหตุผลและคำอธิบายของอัลกอริทึม.) ภายใน glibc ของ_itoaทำเช่นนี้จึงไม่เพียง รีจิสเตอร์ arg-pass ใกล้เคียงกับ x86-64 System V ยกเว้นว่าเรามี arg ใน EAX แทน EDX

เมื่อกลับมา EDI ชี้ไปที่ไบต์แรกของสตริง C ที่สิ้นสุด 0 ในบัฟเฟอร์บัฟเฟอร์ การลงทะเบียนค่าส่งคืนตามปกติคือ EAX / RAX แต่ในภาษาแอสเซมบลีคุณสามารถใช้สิ่งที่เรียกประชุมสิ่งที่สะดวกสำหรับฟังก์ชั่น ( xchg eax,ediในตอนท้ายจะเพิ่ม 1 ไบต์)

buffer_end - ediโทรสามารถคำนวณความยาวอย่างชัดเจนถ้ามันอยากจาก แต่ฉันไม่คิดว่าเราสามารถปรับข้ามเทอร์มิเนเตอร์ได้เว้นแต่ฟังก์ชันจะส่งคืนพอยน์เตอร์ + พอยน์เตอร์หรือพอยน์เตอร์ + ความยาว นั่นจะประหยัดได้ 3 ไบต์ในรุ่นนี้ แต่ฉันไม่คิดว่ามันสมเหตุสมผล

  • EAX = n = หมายเลขที่จะถอดรหัส (สำหรับidiv. args อื่นไม่ใช่ตัวถูกดำเนินการโดยนัย)
  • EDI = จุดสิ้นสุดของบัฟเฟอร์เอาต์พุต (ยังคงใช้รุ่น 64 บิตdec ediดังนั้นจะต้องอยู่ในระดับต่ำ 4GiB)
  • ESI / RSI = ตารางค้นหา, aka LUT ไม่อุดตัน
  • ECX = ความยาวของตาราง = ฐาน ไม่อุดตัน

nasm -felf32 ascii-compress-base.asm -l /dev/stdout | cut -b -30,$((30+10))- (มือแก้ไขเพื่อย่อความคิดเห็นการกำหนดหมายเลขบรรทัดนั้นแปลก)

   32-bit: 17 bytes        ;  64-bit: 18 bytes
                           ; same source assembles as 32 or 64-bit
 3                         %ifidn __OUTPUT_FORMAT__, elf32
 5                         %define rdi edi
 6   address               %define rsi esi
11          machine        %endif
14          code           %define DEF(funcname) funcname: global funcname
16          bytes           
22                         ;;; returns: pointer in RDI to the start of a 0-terminated string
24                         ;;; clobbers:; EDX (tmp remainder)
25                         DEF(ascii_compress_nostring)
27 00000000 C60700             mov     BYTE [rdi], 0
28                         .loop:                    ; do{
29 00000003 99                 cdq                    ; 1 byte shorter than   xor edx,edx / div
30 00000004 F7F9               idiv    ecx            ; edx=n%B   eax=n/B
31                         
32 00000006 8A1416             mov     dl, [rsi + rdx]   ; dl = LUT[n%B]
33 00000009 4F                 dec     edi               ; --output  ; 2B in x86-64
34 0000000A 8817               mov     [rdi], dl         ; *output = dl
35                         
36 0000000C 85C0               test    eax,eax           ; div/idiv don't write flags in practice, and the manual says they're undefined.
37 0000000E 75F3               jnz     .loop         ; }while(n);
38                         
39 00000010 C3                 ret
           0x11 bytes = 17
40 00000011 11             .size: db $ - .start

เป็นเรื่องน่าแปลกใจที่รุ่นที่ง่ายที่สุดที่ไม่มีการแลกเปลี่ยนความเร็ว / ขนาดนั้นเล็กที่สุด แต่std/ cldราคา 2 ไบต์เพื่อใช้stosbในการเรียงลำดับจากมากไปน้อยและยังคงเป็นไปตาม DF = 0 แบบแผนทั่วไป (และ STOS ลดลงหลังจากการจัดเก็บปล่อยให้ตัวชี้ชี้หนึ่งไบต์ต่ำเกินไปเมื่อออกจากลูปทำให้เราต้องเพิ่มไบต์พิเศษเพื่อหลีกเลี่ยง)

รุ่น:

ฉันมาพร้อมกับเทคนิคการใช้งานที่แตกต่างกัน 4 อย่าง (โดยใช้movload / store แบบง่าย ๆ(ด้านบน), การใช้lea/ movsb(เรียบร้อย แต่ไม่เหมาะสม), การใช้xchg/ xlatb/ stosb/ xchgและสิ่งหนึ่งที่เข้าสู่ลูปด้วยแฮ็คคำแนะนำที่ทับซ้อนกันดูรหัสด้านล่าง) . อันสุดท้ายจำเป็นต้องมีการติดตาม0ในตารางการค้นหาเพื่อคัดลอกเป็นเทอร์มินัลสตริงผลลัพธ์ดังนั้นฉันจึงนับว่าเป็น 1 ไบต์ ขึ้นอยู่กับ 32 / 64- บิต (1 ไบต์incหรือไม่) และไม่ว่าเราจะสามารถสันนิษฐานได้ว่าผู้โทรตั้งค่า DF = 1 ( stosbมากไปหาน้อย) หรืออะไรก็ตามรุ่นที่ต่างกันสั้นที่สุด

DF = 1 เพื่อจัดเก็บตามลำดับจากมากไปน้อยทำให้มันชนะสำหรับ xchg / stosb / xchg แต่ผู้โทรมักจะไม่ต้องการสิ่งนั้น รู้สึกเหมือนกำลังถ่ายงานกับผู้โทรด้วยวิธีที่ยากต่อการจัดชิดขอบ (ซึ่งแตกต่างจากการลงทะเบียน arg-through และ return-value แบบกำหนดเองซึ่งโดยทั่วไปแล้วจะไม่เสียค่าใช้จ่ายสำหรับ asm caller ใด ๆ เพิ่มเติม) แต่ในรหัส 64- บิตcld/ scasbทำงานเป็นinc rdiหลีกเลี่ยงการตัดทอนตัวชี้ออกเป็น 32 บิตดังนั้นบางครั้ง ไม่สะดวกในการเก็บรักษา DF = 1 ในฟังก์ชั่น 64 บิต . (ตัวชี้ไปยังรหัสคงที่ / ข้อมูลเป็นแบบ 32 บิตใน x86-64 executable-PIE ที่ไม่ใช่ PIE บน Linux และใน Linux x32 ABI เสมอดังนั้นรุ่น x86-64 ที่ใช้ตัวชี้แบบ 32 บิตนั้นสามารถใช้ได้ในบางกรณี) อย่างไรก็ตาม การโต้ตอบนี้ทำให้น่าสนใจในการดูชุดค่าผสมที่แตกต่างกัน

  • IA32 กับ DF = 0 ในรายการ / ออกจากการเรียกประชุม: 17B (nostring )
  • IA32: 16B (ด้วยการประชุม DF = 1: stosb_edx_argหรือskew) ; หรือ DF ที่เข้ามา = dontcare ปล่อยให้มันตั้ง: 16 + 1Bstosb_decode_overlapหรือ 17Bstosb_edx_arg
  • x86-64 พร้อมพอยน์เตอร์ 64- บิตและ DF = 0 สำหรับการโทรเข้า / ออก: 17 + 1 ไบต์ ( stosb_decode_overlap) , 18B ( stosb_edx_argหรือskew)
  • x86-64 พร้อมพอยน์เตอร์ 64- บิต, การจัดการ DF อื่น ๆ : 16B (DF = 1 skew) , 17B ( nostringด้วย DF = 1, ใช้scasbแทนdec) 18B ( stosb_edx_argรักษา DF = 1 ด้วย 3 ไบต์inc rdi)

    หรือถ้าเราอนุญาตให้ส่งกลับตัวชี้ไปที่ 1 ไบต์ก่อนสตริง15B ( stosb_edx_argโดยไม่incสิ้นสุด) ทั้งหมดตั้งค่าให้เรียกอีกครั้งและขยายสายอักขระอื่นลงในบัฟเฟอร์ด้วยฐาน / ตารางที่แตกต่างกัน ... แต่นั่นจะสมเหตุสมผลมากกว่าถ้าเราไม่ได้หยุดการจัดเก็บ0อย่างใดอย่างหนึ่งและคุณอาจวางฟังก์ชันของฟังก์ชันไว้ในลูป ปัญหาแยกต่างหาก

  • x86-64 พร้อมตัวชี้เอาต์พุต 32 บิต, DF = 0 แบบแผนการเรียก: ไม่มีการปรับปรุงใด ๆ กับตัวชี้เอาต์พุต 64- บิต แต่ 18B ( nostring) เชื่อมโยงกันในขณะนี้

  • x86-64 พร้อมตัวชี้เอาต์พุต 32 บิต: ไม่มีการปรับปรุงใด ๆ กับตัวชี้เวอร์ชัน 64 บิตที่ดีที่สุดดังนั้น 16B (DF = 1 skew) หรือเพื่อตั้งค่า DF = 1 และปล่อยให้เป็น 17B skewด้วยหรือstdไม่cldก็ได้ หรือ 17 + 1B สำหรับstosb_decode_overlapที่มีinc ediในตอนท้ายแทน/cldscasb

ด้วย DF = 1 แผนการโทร: 16 ไบต์ (IA32 หรือ x86-64)

ต้องการ DF = 1 ในอินพุตปล่อยให้ตั้งค่าไว้ อย่างน้อยน่าจะเป็นอย่างน้อยบนพื้นฐานต่อฟังก์ชั่น ทำสิ่งเดียวกับเวอร์ชั่นด้านบน แต่ใช้ xchg เพื่อรับส่วนที่เหลือเข้า / ออก AL ก่อน / หลัง XLATB (ค้นหาตารางด้วย R / EBX เป็นฐาน) และ STOSB ( *output-- = al)

ด้วย DF ปกติ = 0 ในการประชุมเข้า / ออก/ / รุ่นคือ 18 ไบต์สำหรับรหัส 32 และ 64 บิตและ 64 บิตที่สะอาด (ทำงานร่วมกับตัวชี้การส่งออก 64 บิต)stdcldscasb

โปรดทราบว่าอินพุต args อยู่ในการลงทะเบียนที่แตกต่างกันรวมถึง RBX สำหรับตาราง (สำหรับxlatb) นอกจากนี้ทราบว่าวงนี้จะเริ่มต้นด้วยการจัดเก็บ AL, และจบลงด้วยถ่านที่ผ่านมาไม่ได้เก็บไว้เลย (เพราะฉะนั้นmovที่สิ้นสุด) ดังนั้นลูปคือ "เบ้" สัมพันธ์กับชื่ออื่นดังนั้นชื่อ

                            ;DF=1 version.  Uncomment std/cld for DF=0
                            ;32-bit and 64-bit: 16B
157                         DEF(ascii_compress_skew)
158                         ;;; inputs
159                             ;; O in RDI = end of output buffer
160                             ;; I in RBX = lookup table  for xlatb
161                             ;; n in EDX = number to decode
162                             ;; B in ECX = length of table = modulus
163                         ;;; returns: pointer in RDI to the start of a 0-terminated string
164                         ;;; clobbers:; EDX=0, EAX=last char
165                         .start:
166                         ;    std
167 00000060 31C0               xor    eax,eax
168                         .loop:                    ; do{
169 00000062 AA                 stosb
170 00000063 92                 xchg    eax, edx
171                         
172 00000064 99                 cdq                    ; 1 byte shorter than   xor edx,edx / div
173 00000065 F7F9               idiv    ecx            ; edx=n%B   eax=n/B
174                         
175 00000067 92                 xchg    eax, edx       ; eax=n%B   edx=n/B
176 00000068 D7                 xlatb                  ; al = byte [rbx + al]
177                         
178 00000069 85D2               test    edx,edx
179 0000006B 75F5               jnz     .loop         ; }while(n = n/B);
180                         
181 0000006D 8807               mov     [rdi], al     ; stosb would move RDI away
182                         ;    cld
183 0000006F C3                 ret

184 00000070 10             .size: db $ - .start

รุ่นที่ไม่มีการเอียงคล้ายกันนี้จะใช้ EDI / RDI มากกว่าและแก้ไขได้

                            ; 32-bit DF=1: 16B    64-bit: 17B (or 18B for DF=0)
70                         DEF(ascii_compress_stosb_edx_arg)  ; x86-64 SysV arg passing, but returns in RDI
71                             ;; O in RDI = end of output buffer
72                             ;; I in RBX = lookup table  for xlatb
73                             ;; n in EDX = number to decode
74                             ;; B in ECX = length of table
75                         ;;; clobbers EAX,EDX, preserves DF
76                             ; 32-bit mode: a DF=1 convention would save 2B (use inc edi instead of cld/scasb)
77                             ; 32-bit mode: call-clobbered DF would save 1B (still need STD, but INC EDI saves 1)
79                         .start:
80 00000040 31C0               xor     eax,eax
81                         ;    std
82 00000042 AA                 stosb
83                         .loop:
84 00000043 92                 xchg    eax, edx
85 00000044 99                 cdq
86 00000045 F7F9               idiv    ecx            ; edx=n%B   eax=n/B
87                         
88 00000047 92                 xchg    eax, edx       ; eax=n%B   edx=n/B
89 00000048 D7                 xlatb                  ; al = byte [rbx + al]
90 00000049 AA                 stosb                  ; *output-- = al
91                         
92 0000004A 85D2               test    edx,edx
93 0000004C 75F5               jnz     .loop
94                         
95 0000004E 47                 inc    edi
96                             ;; cld
97                             ;; scasb          ; rdi++
98 0000004F C3                 ret
99 00000050 10             .size: db $ - .start
    16 bytes for the 32-bit DF=1 version

ฉันลองรุ่นอื่นของสิ่งนี้ด้วย lea esi, [rbx+rdx]/ movsbเป็นตัววนรอบด้านใน (RSI ถูกรีเซ็ตทุกการทำซ้ำ แต่ลดลง RDI) แต่มันไม่สามารถใช้ xor-zero / stos สำหรับเทอร์มิเนเตอร์ดังนั้นจึงมีขนาดใหญ่กว่า 1 ไบต์ (และไม่สะอาด 64 บิตสำหรับตารางการค้นหาโดยไม่มีคำนำหน้า REX ใน LEA)


LUT ที่มีความยาวอย่างชัดเจนและ 0 terminator: 16 + 1 bytes (32- บิต)

รุ่นนี้ตั้งค่า DF = 1 และปล่อยให้เป็นเช่นนั้น ฉันกำลังนับไบต์พิเศษ LUT ที่ต้องการเป็นส่วนหนึ่งของจำนวนไบต์ทั้งหมด

เคล็ดลับเย็นที่นี่จะมีไบต์เดียวกันถอดรหัสสองวิธีที่แตกต่างกัน เราตกลงไปในช่วงกลางของลูปที่มีเศษเหลือ = ฐานและ quotient = จำนวนอินพุตและคัดลอก 0 เทอร์มิเนเตอร์เข้าที่

ในครั้งแรกที่ผ่านฟังก์ชั่น 3 ไบต์แรกของลูปจะถูกใช้เป็นไบต์สูงของ disp32 สำหรับ LEA หน่วยงาน LEA นั้นทำการคัดลอกฐาน (โมดูลัส) ไปยัง EDX idivสร้างส่วนที่เหลือสำหรับการทำซ้ำในภายหลัง

ไบต์ที่สองของidiv ebpคือFDซึ่งเป็น opcode สำหรับstdคำสั่งที่ฟังก์ชันนี้จำเป็นต้องใช้ (นี่คือการค้นพบที่โชคดีฉันได้ดูสิ่งนี้divก่อนหน้านี้ซึ่งแยกตัวเองจากการidivใช้/rบิตใน ModRM ไบต์ที่ 2 ของการdiv epbถอดรหัสเป็นcmcซึ่งไม่เป็นอันตราย แต่ไม่เป็นประโยชน์ แต่idiv ebpจริง ๆ แล้วเราสามารถลบสิ่งที่stdอยู่ด้านบนออก ของฟังก์ชัน)

หมายเหตุการลงทะเบียนอินพุตนั้นต่างกันอีกครั้ง: EBP สำหรับฐาน

103                         DEF(ascii_compress_stosb_decode_overlap)
104                         ;;; inputs
105                             ;; n in EAX = number to decode
106                             ;; O in RDI = end of output buffer
107                             ;; I in RBX = lookup table, 0-terminated.  (first iter copies LUT[base] as output terminator)
108                             ;; B in EBP = base = length of table
109                         ;;; returns: pointer in RDI to the start of a 0-terminated string
110                         ;;; clobbers: EDX (=0), EAX,  DF
111                             ;; Or a DF=1 convention allows idiv ecx (STC).  Or we could put xchg after stos and not run IDIV's modRM
112                         .start:
117                             ;2nd byte of div ebx = repz.  edx=repnz.
118                             ;            div ebp = cmc.   ecx=int1 = icebp (hardware-debug trap)
119                             ;2nd byte of idiv ebp = std = 0xfd.  ecx=stc
125                         
126                             ;lea    edx, [dword 0 + ebp]
127 00000040 8D9500             db  0x8d, 0x95, 0   ; opcode, modrm, 0 for lea edx, [rbp+disp32].  low byte = 0 so DL = BPL+0 = base
128                             ; skips xchg, cdq, and idiv.
129                             ; decode starts with the 2nd byte of idiv ebp, which decodes as the STD we need
130                         .loop:
131 00000043 92                 xchg    eax, edx
132 00000044 99                 cdq
133 00000045 F7FD               idiv    ebp            ; edx=n%B   eax=n/B;
134                             ;; on loop entry, 2nd byte of idiv ebp runs as STD.  n in EAX, like after idiv.  base in edx (fake remainder)
135                         
136 00000047 92                 xchg    eax, edx       ; eax=n%B   edx=n/B
137 00000048 D7                 xlatb                  ; al = byte [rbx + al]
138                         .do_stos:
139 00000049 AA                 stosb                  ; *output-- = al
140                         
141 0000004A 85D2               test    edx,edx
142 0000004C 75F5               jnz     .loop
143                         
144                         %ifidn __OUTPUT_FORMAT__, elf32
145 0000004E 47                 inc     edi         ; saves a byte in 32-bit.  Makes DF call-clobbered instead of normal DF=0
146                         %else
147                             cld
148                             scasb          ; rdi++
149                         %endif
150                         
151 0000004F C3                 ret
152 00000050 10             .size: db $ - .start
153 00000051 01                     db 1   ; +1 because we require an extra LUT byte
       # 16+1 bytes for a 32-bit version.
       # 17+1 bytes for a 64-bit version that ends with DF=0

เคล็ดลับการถอดรหัสที่ทับซ้อนกันนี้ยังสามารถใช้กับcmp eax, imm32: ใช้เวลาเพียง 1 ไบต์เพื่อข้ามไปข้างหน้าอย่างมีประสิทธิภาพ 4 ไบต์เพียงธงอุดตัน (นี่เป็นเรื่องที่แย่มากสำหรับประสิทธิภาพของ CPU ที่ทำเครื่องหมายขอบเขตการเรียนการสอนในแคช L1i, BTW)

แต่ที่นี่เราใช้ 3 ไบต์เพื่อคัดลอกรีจิสเตอร์และกระโดดเข้าไปในลูป ปกติแล้วจะใช้เวลา 2 + 2 (mov + jmp) และให้เรากระโดดเข้าไปในลูปก่อนหน้า STOS แทนก่อน XLATB แต่เราต้องการ STD แยกต่างหากและมันก็ไม่น่าสนใจมาก

ลองออนไลน์! (กับ_startผู้โทรที่ใช้sys_writeกับผลลัพธ์)

เป็นการดีที่สุดสำหรับการดีบั๊กเพื่อให้ทำงานภายใต้straceหรือลบ hexdump เอาท์พุทดังนั้นคุณสามารถดูการตรวจสอบว่ามีเทอร์\0มินัลในตำแหน่งที่ถูกต้องและอื่น ๆ แต่คุณสามารถดูว่ามันใช้งานได้จริงและผลิตAAAAAACHOOเพื่อป้อนเข้า

num  equ 698911
table:  db "CHAO"
%endif
    tablen equ $ - table
    db 0  ; "terminator" needed by ascii_compress_stosb_decode_overlap

(อันที่จริงแล้วxxAAAAAACHOO\0x\0\0...เพราะเราทิ้งจาก 2 ไบต์ก่อนหน้านี้ในบัฟเฟอร์ออกไปจนถึงความยาวคงที่ดังนั้นเราจะเห็นได้ว่าฟังก์ชั่นเขียนไบต์ที่มันควรจะเป็นและไม่ได้เหยียบไบต์ใด ๆ ที่มันไม่ควร start-pointer ที่ส่งผ่านไปยังฟังก์ชันคือxอักขระตัวที่ 2 ซึ่งตามด้วยศูนย์)


3

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

ṙ1ṃ@

ลองออนไลน์!

เป็นตัวในตัวสำหรับสิ่งนี้ อีกสามไบต์บัญชีสำหรับการสร้างดัชนีหนึ่งเดียวของเยลลี่


จากความอยากรู้ทำไมเจลลี่ถึงมีการบีบอัด " เบสในตัวแปลง x เป็นความยาวฐาน (y) แล้วสร้างดัชนีเป็น y " เป็นกรณีที่ยอดเยี่ยมมากที่ฐานที่คุณมดแปลงและความยาวของสตริง / จำนวนเต็ม / รายการเท่ากันหรือไม่ เมื่อฉันค้นหาคำตอบฉันสามารถค้นหาคำตอบได้สามข้อเท่านั้น: 1 ; 2 ; 3 . ค่อนข้างแปลกในตัวในทุกวันท้าทายกอล์ฟรหัส imo : S
Kevin Cruijssen

3
@KevinCruijssen มันมีประโยชน์มากเมื่อคุณต้องการแปลงNเป็นฐานสิบหกโดยใช้ตัวอักษรฐานสิบหกแทนรายการตัวเลข
นาย Xcoder

@KevinCruijssen มันเป็นวิธีการบีบอัดสำหรับสตริง ในตัวอย่างแรกสตริงที่ต้องการคือ“sspspdspdspfdspfdsp”แต่เมื่อ“çƥ÷£ḟ’ṃ“spdf”¤คุณบันทึกหกไบต์ มันมีประโยชน์อย่างยิ่งกับหมายเลขฐานของ Jelly
dylnan


3

Charcoal , 3 1 ไบต์

θη

ลองออนไลน์! การเชื่อมโยงคือการใช้รหัสเวอร์ชันอย่างละเอียด แก้ไข: บันทึก 2 ไบต์ด้วย @ ASCII เท่านั้น เวอร์ชันก่อนหน้านี้ก่อนเพิ่ม builtin จะมี 8 ไบต์:

⭆↨θLη§ηι

ลองออนไลน์! การเชื่อมโยงคือการใช้รหัสเวอร์ชันอย่างละเอียด คำอธิบาย:

    η       Second input
   L        Length
  θ         First input
 ↨          Base convert to array
⭆           Map over values and join
      η     Second input
       ι    Current value
     §      Index into list
            Implicitly print result

ที่จริงแล้วมันควรจะทำงานอยู่แล้ว แต่เห็นได้ชัดว่าฉันได้ทำผิดพลาดอีกครั้ง> _>
ASCII- เท่านั้น

นอกจากนี้จริง ๆ แล้วมันจะเป็น1 ไบต์ : P (ขณะนี้แตกดังนั้นฉันไม่ได้ใช้หมายเลขและอาร์เรย์สตริงเป็นอาร์กิวเมนต์) (เช่นฉันสงสัยว่า (ยกเลิก) การป้อนข้อมูลโดยนัยที่มีประโยชน์)
ASCII-only

@ ASCII- อย่างเดียวคุณไม่ได้หมายถึง "1 ไบต์" (ดูเอาต์พุต -vl ของคุณ ;-) นอกจากนี้การป้อนข้อมูลโดยนัยดูเหมือนจะไร้ประโยชน์เกือบใน Charcoal ยกเว้นความท้าทายเช่นนี้
Neil

1
@ ASCII เพียงพหูพจน์ "ไบต์" แทน "ไบต์" เอกพจน์คือความหมายของนีล ;) สำหรับคำตอบ 1 ไบต์ของคุณทำไมถึงขีดฆ่าθη? ดูน่าสับสนเล็กน้อย ทำไมไม่เพียง แต่เอามันสมบูรณ์และปล่อย?
Kevin Cruijssen

1
@Nit ฉันตรวจสอบอีกครั้งและมีการเพิ่มในตัวก่อนที่คำถามจะถูกถาม แต่ฉันไม่ได้ตระหนักเพราะมีข้อผิดพลาด
Neil

3

D , 112 ไบต์

import std.conv;C u(C,I)(I n,C b){C t;for(I l=b.length;n;n/=l)t=to!C(n%l)~t;foreach(ref c;t)c=b[c-48];return t;}

ลองออนไลน์!

นี่คือพอร์ตของคำตอบ C ++ของHatsuPointerKun

รูปแบบการโทรคือu(ulong(n), to!(char[])(b))ที่ไหนnและbเป็นอาร์กิวเมนต์ซ้ายและขวา

D สิ่งที่เฉพาะเจาะจง

น่าเศร้าที่เราต้องนำเข้าstd.convเพื่อทำการแปลงประเภทใด ๆ ที่อยู่เหนือการแปลงประเภทพื้นฐานมาก

โดยใช้ระบบแม่แบบ golfy และให้ฟังก์ชั่นชนิดที่จำเป็น (ซึ่งเป็นเหตุผลที่เรียกมันไม่ได้เป็นเพียงu(n,b)) เราสามารถลดการเกิดขึ้นของchar[]และulongเพื่อ1ไบต์แต่ละเมื่อภายในฉฟังก์ชั่น

D เริ่มต้นประเภทของเราสำหรับเราดังนั้นจึงC t;สั้นC t=cast(char[])([])

to!Cแปลงจำนวนเต็มn%lเป็นอาร์เรย์อักขระ (โดยใช้ codepoints) และทำการ~ต่อข้อมูล

foreach(ref c;t)ก็เหมือนกับfor(... : ...)วงวนของ C ++ แต่อีกหน่อย refเป็นเหมือน&มันถือว่าcเป็นคัดลอกโดยอ้างอิง (เช่นเราสามารถแก้ไขt) โชคดีที่ D infers ประเภทที่cไม่มีคำว่า denoting ประเภทใด ๆ



3

C ++, 150 144 ไบต์, uint64อินพุต

-6 ไบต์ขอบคุณZacharý

#include<string>
using s=std::string;s u(uint64_t n,s b){s t;for(;n;n/=b.size())t=std::to_string(n%b.size())+t;for(auto&a:t)a=b[a-48];return t;}

การใช้ตัวแปรเพื่อจัดเก็บขนาดจะเพิ่มจำนวน bytecount 1

วิธีเรียกใช้ฟังก์ชัน:

u(2740, "|_")

ก่อนอื่นจำนวนที่สองคือสตริง (อาร์เรย์ char)

กรณีทดสอบ:

std::cout << u(2740, "|_") << '\n' << u(698911, "chao") << '\n';
return 0;

1
3 ไบต์เพื่อโกนออก: คุณไม่ต้องการพื้นที่หลังจาก#includeนั้นคุณสามารถเปลี่ยน;;เป็นเพียง;และ'0'สามารถเป็นได้48
Zacharý

1
ยิ่งไปกว่านั้น, วงวนในขณะนั้นอาจเป็นforลูป:for(;n;n/=b.size())t=std::to_string(n%b.size())+t;
Zacharý

@ceilingcat ฉันลืมไปว่าb.size()ไม่เปลี่ยนในวงนั้น
Zacharý

@ceilingcat นั่นจะเพิ่มจำนวน bytec โดย 1 แทนที่จะลดลง
HatsuPointerKun

2

Twig, 66 ไบต์

สร้าง a macroที่ต้องถูกimportแก้ไขในเทมเพลต

{%macro d(n,c)%}{%for N in n|split%}{{c[N]}}{%endfor%}{%endmacro%}

คาดหวังค่า:

สำหรับอาร์กิวเมนต์แรก ( n):

  • จำนวน
  • เชือก

สำหรับอาร์กิวเมนต์ที่สอง ( c):

  • อาเรย์ของตัวเลข
  • อาร์เรย์ของสตริง

วิธีใช้:

  • สร้าง.twigไฟล์
  • เพิ่ม {% import 'file.twig' as uncompress %}
  • เรียกแมโคร uncompress.d()

Ungolfed (ไม่ใช่หน้าที่):

{% macro d(numbers, chars) %}
    {% for number in numbers|split %}
        {{ chars[number] }}
    {% endfor %}
{% endmacro %}


คุณสามารถทดสอบรหัสนี้ได้ที่: https://twigfiddle.com/54a0i9


2

Pyth, 9 8 7 ไบต์

s@LQjEl

บันทึกเป็นไบต์ด้วย hakr14 และอีกตัวต้องขอบคุณ Mr. Xcoder
ลองที่นี่

คำอธิบาย

s@LQjEl
    jElQ      Convert the second input (the number) to the appropriate base.
 @LQ          Look up each digit in the list of strings.
s             Add them all together.

บันทึกไบต์โดยแทนที่m@Qdด้วย@LQ
hakr14

บันทึกไบต์โดยการแทนที่ด้วยvz E
นาย Xcoder

2

C89, การ จำกัด ช่วงเวลาint n, 64 53 ไบต์

  • changelog: ใช้char **outและแก้ไขมันแทนที่จะเอากลับมาchar *

ใช้ตัวเลขเป็นintตารางการค้นหาเป็นอาร์เรย์ + ความยาว
char *outbufเอาท์พุทจะถูกเขียนลงใน ผู้เรียกผ่าน (โดยการอ้างอิง) ตัวชี้ไปยังจุดสิ้นสุดของบัฟเฟอร์ ฟังก์ชั่นปรับเปลี่ยนตัวชี้ที่จะชี้ไปที่ไบต์แรกของสตริงเมื่อกลับมา

g(n,I,B,O)char*I,**O;{for(**O=0;n;n/=B)*--*O=I[n%B];}

นี่เป็น C89 ที่ถูกต้องและทำงานอย่างถูกต้องแม้เปิดใช้งานการปรับให้เหมาะสมที่สุด เช่นไม่ได้ขึ้นอยู่กับ-O0พฤติกรรมของgcc เมื่อล้มลงในตอนท้ายของฟังก์ชั่นที่ไม่เป็นโมฆะหรือมี UB อื่น ๆ

ผ่านตัวชี้ไปยังจุดสิ้นสุดของบัฟเฟอร์เป็นปกติสำหรับการเพิ่มประสิทธิภาพ int-> ฟังก์ชั่นสตริงเช่นglibc _itoaภายใน ดูคำตอบนี้สำหรับคำอธิบายโดยละเอียดเกี่ยวกับการแบ่งจำนวนเต็มเป็นหลักด้วยการวนซ้ำ div / mod เหมือนกับที่เราทำที่นี่ใน C และ x86-64 asm หากฐานเป็นพลังของ 2 คุณสามารถเลื่อน / ปิดบังเพื่อแยกตัวเลข MSD ก่อน แต่อย่างอื่นตัวเลือกที่ดีเท่านั้นคือตัวเลขที่มีนัยสำคัญน้อยที่สุดก่อน (พร้อมโมดูโล)

ลองออนไลน์! . เวอร์ชันที่ไม่ถูกปรับแต่ง:

/* int n = the number
 * int B = size of I = base
 * char I[] = input table
 * char **O = input/output arg passed by ref:
 *    on entry: pointer to the last byte of output buffer.
 *    on exit:  pointer to the first byte of the 0-terminated string in output buffer
 */
void ungolfed_g(n,I,B,O)char*I,**O;
{
    char *outpos = *O;     /* Golfed version uses *O everywhere we use outpos */
    *outpos = 0;           /* terminate the output string */
    for(;n;n/=B)
        *--outpos = I[n%B]; /* produce 1 char at a time, decrementing the output pointer */
    *O = outpos;
}

ในรุ่นที่มีความยาวอย่างชัดเจนนี้การป้อนข้อมูลที่เป็นchar table[]ซึ่งไม่ไม่จำเป็นต้องยุติ 0 ไบต์เพราะเราไม่เคยรักษามันเป็นสตริง มันอาจเป็นint table[]สิ่งที่เราใส่ใจ C ไม่มีคอนเทนเนอร์ที่ทราบความยาวของตัวเองดังนั้นพอยน์เตอร์ + ความยาวจึงเป็นวิธีปกติในการส่งอาเรย์ด้วยขนาด strlenดังนั้นเราจึงเลือกว่าแทนที่จะต้องไป

ขนาดบัฟเฟอร์สูงสุดมีค่าประมาณsizeof(int)*CHAR_BIT + 1ดังนั้นจึงมีค่าคงที่เล็กและรวบรวม (เราใช้พื้นที่มากกับ base = 2 และบิตทั้งหมดที่ตั้งค่าเป็น 1) เช่น 33 ไบต์สำหรับจำนวนเต็ม 32 บิตรวมถึงเทอร์0มิเนเตอร์


C89, ที่เซ็นชื่อint, ตารางเป็นสตริง C ที่มีความยาวโดยนัย, 65 ไบต์

B;f(n,I,O)char*I,**O;{B=strlen(I);for(**O=0;n;n/=B)*--*O=I[n%B];}

นี่คือสิ่งเดียวกัน แต่อินพุตเป็นสตริงความยาวโดยนัยดังนั้นเราต้องค้นหาความยาวด้วยตนเอง


2

ยูทิลิตี Bash + core , 49 ไบต์

dc -e`echo -en $2|wc -c`o$1p|tr -dc 0-9|tr 0-9 $2

ลองออนไลน์!

ความเห็น / คำอธิบาย

นี่ใช้อาร์กิวเมนต์บรรทัดคำสั่งเป็นอินพุต (ตัวเลขในฐาน 10 จากนั้นเป็นสตริงเดี่ยวที่มีรายการอักขระ) และเอาต์พุตไปยัง stdout อักขระพิเศษเช่นช่องว่างบรรทัดใหม่ ฯลฯ อาจถูกป้อนในรูปแบบเลขฐานแปด (ตัวอย่างเช่น\040สำหรับช่องว่าง) หรือ\nสำหรับบรรทัดใหม่\tสำหรับแท็บหรือลำดับการหลบหลีกอื่น ๆ ที่echo -eและtrตีความเหมือนกัน

ไบต์จำนวนมากที่นี่เพื่อจัดการอักขระพิเศษและกรณีทดสอบขนาดใหญ่ หากฉันต้องจัดการกับตัวละครที่ไม่น่ากลัวและตัวเลขมีขนาดเล็ก (ตัวอย่างเช่นกรณีทดสอบครั้งแรก) 24 ไบต์ต่อไปนี้จะทำ:

dc -e${#2}o$1p|tr 0-9 $2

สิ่งนี้ใช้การขยายพารามิเตอร์${#2}เพื่อให้ได้จำนวนอักขระในสตริงสร้างโปรแกรม dc เพื่อทำการแปลงฐานแล้วส่งตัวเลขที่แปลงtrแล้ว

นี้จะไม่จัดการกับการขึ้นบรรทัดใหม่หรือช่องว่างหรือแท็บ แต่เพื่อที่จะจัดการกับลำดับหนีโดยไม่ต้องมีผลกระทบต่อฐานที่ฉันจะนับจำนวนตัวอักษรหลังจากการตีความหนีด้วยwc -c echo -enนี่เป็นการขยายโปรแกรมเป็น 38 ไบต์:

dc -e`echo -en $2|wc -c`o$1p|tr 0-9 $2

น่าเสียดายที่ dc มี "คุณสมบัติ" ที่น่ารำคาญซึ่งถ้ามันแสดงผลเป็นจำนวนมากมันจะทำการพันด้วย slash + newline ลำดับดังนั้นกรณีทดสอบที่ใหญ่กว่าจึงมีเอาต์พุตพิเศษนี้ หากต้องการลบออกฉันจะส่งเอาต์พุตของ dc tr -dc 0-9ไปยังเพื่อลบอักขระที่ไม่ใช่ตัวเลข และที่นั่นเรา


ฉันจะแนะนำdc -e${#2}o$1p|tr 0-9 "$2"ให้ใช้อินพุตอย่างแท้จริงแทนที่จะอยู่ในรูปแบบ \ escaped ดังนั้นจึงสามารถจัดการช่องว่างได้ แต่trไม่มีตัวเลือกที่จะไม่ถือว่า-เป็นอักขระช่วงเช่น หากอินพุต-ไม่ได้อยู่ที่ปลายด้านหนึ่งของสตริงมันจะแตก sed "y/0123456789/$2/"บางทีคุณอาจจะสามารถใช้ ไม่ฉันเดาไม่ GNU sedต้องการให้ทั้งคู่yมีความยาวเท่ากันและดูเหมือนจะทำให้หายใจไม่ออกในบรรทัดใหม่
Peter Cordes

2

APL (Dyalog Unicode) , 14 13 12 ไบต์

⊢⌷⍨∘⊂⊥⍣¯1⍨∘≢

ลองออนไลน์!

ฟังก์ชั่นมัดเงียบ; ไม่สามารถจัดการกับกรณีทดสอบที่ใหญ่ที่สุดได้เนื่องจากการเป็นตัวแทนจุดลอยตัว

บันทึกแล้ว1 2 ไบต์ขอบคุณ @ Adám!

13 ไบต์เพิ่มสำหรับส่วนหัว: ⎕IO←0: ฉัน nDex O rigin = 0 และ⎕FR←1287: F loat R epresentation = 128 บิต (ฉันลืมไปเลยว่านี่ไม่สามารถใช้ได้ )

อย่างไร?

⊢⌷⍨∘⊂⊥⍣¯1⍨∘≢    Tacit function, infix.
               Tally (number of elements in) the right argument.
         ⍨∘     Then swap the arguments of
     ⊥⍣¯1       Base conversion (to base ≢<r_arg>)
               Enclose (convert to an array)
  ⍨∘            Then swap the arguments of
               Index
               (Into) the right argument.


1

Canvas ขนาด 7 ไบต์

L┬{╵⁸@p

ลองที่นี่!

การดำเนินการไปข้างหน้า:

L┬{╵⁸@p
L      get the length of the input (popping the item)
 ┬     base decode the other input
  {    for each number there
   ╵     increment
    ⁸@   in the 1st input get that numbered item
      p  and output that

ชุดอักขระอินพุตอาจเป็นสตริงได้ตราบใดที่ไม่มีบรรทัดใหม่เนื่องจาก Canvas ไม่มีอักขระขึ้นบรรทัดใหม่และแปลงเป็นวัตถุ 2D โดยอัตโนมัติ



1

SOGL V0.12 , 10 ไบต์

l;A─{IaWp}

ลองที่นี่!

พริตตี้ยาวพิจารณาจากความคิดที่จะดำเนินการสวยมากในภาษาที่: ที่นี่เข้า

¶    __   __    ¶   |  |_|  |   ¶___|       |___¶-   -   -   -  ¶ - - - - - - - ¶- - - - - - - -¶_______________¶

ให้สตริงที่บีบอัดโดยใช้วิธีนี้



1

Stax , 2 ไบต์

:B

เรียกใช้และแก้ไขข้อบกพร่อง

:Bเป็นคำสั่งใน stax ที่ทำสิ่งนี้ ปกติแล้วมันจะทำงานบน "string" * แทนที่จะเป็นอาร์เรย์ของ "strings" ในท้ายที่สุดนี้หมายความว่าการส่งออกเป็นอาร์เรย์ของอาร์เรย์อักขระเดียว แต่เอาท์พุทโดยปริยายแบนอยู่แล้ว

* Stax ไม่มีประเภทสตริง ข้อความถูกแทนด้วยอาร์เรย์จำนวนเต็มของ codepoints



มีมากมาย ฉันเคยเพิ่มคำแนะนำให้กับ stax ที่มีอยู่แล้วและฉันลืมไปแล้ว (อาเรย์จะไม่ลดลง?)
เรียกซ้ำ



1

C (gcc) , 110 ไบต์

char s[99],S[99];i;f(x,_)char*_;{i=strlen(_);*s=*S=0;while(x)sprintf(S,"%c%s",_[x%i],s),strcpy(s,S),x/=i;x=s;}

ลองออนไลน์!

รายละเอียด:

char s[99],S[99];           // Two strings, s and S (capacity 99)
i;                          // A variable to store the length of the string
f(x,_)char*_;{              // f takes x and string _
    i=strlen(_);            // set i to the length of _
    *s=*S=0;                // empty s and S
    while(x)                // loop until x is zero
        sprintf(S,"%c%s",   // print into S a character, then a string
                _[x%i],s),  // character is the x%i'th character of _, the string is s
        strcpy(s,S),        // copy S into s
        x/=i;               // divide x by the length of the string (and loop)
    x=s;}                   // return the string in s

1
หากคุณเริ่มต้นในตอนท้ายของบัฟเฟอร์และทำงานย้อนหลังคุณสามารถหลีกเลี่ยงsprintfได้ เวอร์ชัน C ของฉันคือ 53 ไบต์พร้อมบัฟเฟอร์เอาต์พุตที่ผู้โทรกำหนด คุณสามารถทำมันได้strcpyในตอนท้ายหากคุณต้องการคัดลอกไบต์ไปยังจุดเริ่มต้นของบัฟเฟอร์
Peter Cordes

นั่นคือยอดเยี่ยม ฉันไม่สนใจว่ามันเป็นรูปแบบ I / O ที่น่าอึดอัดใจหรือไม่ I / O ที่น่าอึดอัดใจคือ C อ้างว่ามีชื่อเสียง! ทำได้ดีฉันขอแนะนำให้ใส่ลงในโพสต์เคล็ดลับ C
LambdaBeta

โพสต์คำตอบเกี่ยวกับเคล็ดลับสำหรับการเล่นกอล์ฟใน Cอธิบายและให้เหตุผลเทคนิค
ปีเตอร์กอร์เดส

1

CJam , 11 ไบต์

liq_,@\b\f=

ลองออนไลน์!รับอินพุตเป็นตัวเลขตามด้วยบรรทัดใหม่แล้วตามด้วยอักขระในรูปแบบ ASCII

คำอธิบาย

li           e# Read the first line and convert it to an integer
  q_,        e# Read the rest of the input and push its length n
     @\b     e# Convert the number to its base-n equivalent, as an array of numbers
        \f=  e# Map over the array, taking each element's index from the string

ตั้งแต่ "IO ยืดหยุ่นได้" ฉันคิดว่าคุณสามารถกำจัดliqจุดเริ่มต้นได้และนั่นจะช่วยให้คุณประหยัดได้ 3 ไบต์!
Chromium

1

JavaScript ขนาด 39 ไบต์

ท่าเรือร็อดทางออกหลาม

s=>g=n=>n?g(n/(l=s.length)|0)+s[n%l]:""

ลองออนไลน์


ใช้งานnได้สูงสุด 64 บิตใช่ไหม (Python มีจำนวนเต็มที่มีความแม่นยำตามอำเภอใจ แต่ตัวเลข JS นั้นเป็นdoubleความแม่นยำแบบลอยตัวที่สามารถแปลงเป็นจำนวนเต็มได้) ดูเหมือนจะไม่ได้ผลกับกรณีทดสอบขนาดใหญ่ในคำถามเช่น 19281493256706472449121007892136266165608611308594314869901490990149090909090909079060908974660758972167966 โอ้ แต่คำถามให้คำตอบเช่นนั้น ยังคงควรสังเกต
Peter Cordes

1

SimpleTemplateขนาด 86 ไบต์

ว้าวนี่เป็นความท้าทายที่ยิ่งใหญ่!

สิ่งนี้ทำยากเนื่องจากขาดการเข้าถึงดัชนีเฉพาะโดยตรงเมื่อดัชนีเป็นตัวแปร
ข้อผิดพลาดทำให้มันอีกต่อไปต้องเก็บค่าภายในตัวแปร

{@setA argv.1}{@eachargv.0}{@setC C,"{@echoA.",_,"}"}{@calljoin intoC"",C}{@/}{@evalC}

คาดหวังค่า:

อาร์กิวเมนต์แรก ( argv.0) สามารถ:

  • จำนวนเต็ม
  • สตริงที่มีตัวเลข
  • อาร์เรย์ของจำนวนเต็ม

อาร์กิวเมนต์ที่สอง ( argv.1) สามารถ:

  • สตริง
  • อาเรย์

มันทำงานอย่างไร

มันทำงานด้วยวิธีนี้:

  • วนรอบจำนวน / สตริงที่ส่งผ่านเป็นอาร์กิวเมนต์แรก
  • ตั้งค่าตัวแปรCให้เป็นอาร์เรย์ที่มี:
    • ค่าก่อนหน้า C
    • สตริง "{@echoA."
    • ค่าของการวนซ้ำ
    • สตริง "}"
  • ร่วมทุกอย่างร่วมกัน (โดยใช้ PHP ของjoinฟังก์ชั่น)
    ผลการนี้ตัวอย่างเช่นCมี"{@echoA.0}{@echoA.1}..."
  • ประเมินผลลัพธ์ของ C

Ungolfed:

{@set args argv.1}
{@each argv.0 as number}
    {@set code code, "{@echo args.", number , "}"}
    {@call join into code "", code}
{@/}
{@eval code}

คุณสามารถลองใช้รหัสนี้ได้ที่: https://ideone.com/NEKl2q


ผลลัพธ์ที่ดีที่สุด

หากไม่มีข้อบกพร่องนี่จะเป็นผลลัพธ์ที่ดีที่สุดโดยคำนึงถึงข้อ จำกัด (77 ไบต์):

{@eachargv.0}{@setC C,"{@echoargv.1.",_,"}"}{@calljoin intoC"",C}{@/}{@evalC}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.