ASCII-Dekomprimierung von einer Basis-n-Zahl

24

Dies ist inspiriert von einer 05AB1E-Antwort von Magic Octupus Urn .

Ausgehend von zwei Argumenten, einer positiven Ganzzahl und einer Zeichenfolge / Zeichenliste:

  1. Übersetzen Sie die Zahl in base-n, wobei n die Länge der Zeichenfolge ist.
  2. Ersetzen Sie für jedes Zeichen jedes Erscheinungsbild des Index dieses Zeichens in der Zahl zur Basis n durch dieses Zeichen.
  3. Drucken Sie die neue Zeichenfolge aus oder geben Sie sie zurück.

Beispiele:

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:
_===_
(.,.)
( : )
( : )

Regeln:

  • IO ist flexibel .
    • Sie können die Zahl in einer beliebigen Basis verwenden, solange sie zwischen den Eingaben konsistent ist
    • Die Liste der Zeichen muss jedoch 0-indiziert sein, wobei 0 das erste Zeichen und n-1 das letzte ist
  • Mögliche Zeichen können beliebige druckbare ASCII-Zeichen sowie Leerzeichen wie Tabulatoren und Zeilenumbrüche sein
  • Die angegebene Liste der Zeichen hat eine Länge im Bereich 2-10einschließlich. Das heißt, die kleinste Basis ist binär und die größte ist dezimal ( keine lästigen Buchstaben hier )
  • Standardlücken sind verboten
  • Sie können jederzeit antworten, auch wenn Ihre Sprache die größeren Testfälle nicht bewältigen kann.

Da dies , gewinnt der kürzeste Code für jede Sprache. ( Ich weiß, dass alle Ihre Golfsprachen ein Byte integrierte Funktionen haben ;)

Scherzen
quelle
Sandbox (gelöscht)
Jo King
3
D'awwh, ich fühle mich geehrt. 05AB1E ascii-art war vor einiger Zeit mein Favorit.
Magic Octopus Urn
Sie können eine neue Herausforderung erstellen: Suchen Sie die Permutation von Zeichen im Array, um die Anzahl zu minimieren :)
mazzy

Antworten:

8

05AB1E , 7 6 Bytes

gв¹sèJ

Da es von einer 05AB1E-Antwort inspiriert wurde, scheint eine Antwort in 05AB1E passend. :)

-1 Byte dank @Enigma, indem foreach entfernt und dies implizit getan wird.

Probieren Sie es online aus oder überprüfen Sie alle Testfälle .

Erläuterung:

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)
Kevin Cruijssen
quelle
1
gв¹sèJein Byte speichern.
Emigna
@Emigna Danke. Ich kann nicht glauben, dass ¹sèich jetzt nicht an mich selbst gedacht habe. (Ich wusste, dass das Ändern von ?in Jin diesem Fall die gleiche Ausgabe ergibt.)
Kevin Cruijssen
6

Java 8, 72 50 Bytes

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

-22 Bytes dank @ OlivierGrégoire durch Rückgabe eines IntStreamanstatt direkt zu drucken.

Probieren Sie es online aus .

Erläuterung:

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`
Kevin Cruijssen
quelle
2
a->n->n.toString(a.length).chars().map(c->a[c-48])(50 Bytes) seit "IO ist flexibel"
Olivier Grégoire
String f(char[]a,int n){return n>0?f(a,n/a.length)+a[n%a.length]:"";}(69 Bytes) rekursiv, zum Spaß.
Olivier Grégoire
6

Python 3 , 49 Bytes

Kann noch nicht kommentieren, daher poste ich die Python 2-Antwort, die an Python 3.5 angepasst ist.

f=lambda n,s:n and f(n//len(s),s)+s[n%len(s)]or''
Romzie
quelle
2
Willkommen bei PPCG! Fügen Sie einen TIO-Link hinzu , um Ihre Lösung vorzustellen .
Jo King
5

Japt, 2 Bytes

Kann die zweite Eingabe als Array oder String annehmen. Schlägt die letzten 2 Testfälle fehl, da die Zahlen die maximale Ganzzahl von JavaScript überschreiten. Ersetzen Sie sdurch ì, um stattdessen ein Array von Zeichen auszugeben.

sV

Versuch es

Zottelig
quelle
5

Haskell , 40 39 Bytes

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

Probieren Sie es online!

Da Haskells IntTyp auf beschränkt ist 9223372036854775807, schlägt dies bei größeren Zahlen fehl.

-1 Byte dank 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)

Probieren Sie es online!

ovs
quelle
Gute Idee, cyclestatt zu verwenden mod! div n(length l)Speichert ein Byte.
Laikoni
4

MATL , 2 Bytes

YA

Probieren Sie es online!

Eingaben sind eine Zahl und eine Zeichenfolge.

Schlägt 2^53aufgrund der Gleitkomma-Genauigkeit fehl , wenn die Anzahl überschritten wird.

Erläuterung

Was weißt YAdu, ein Builtin (Basisumwandlung mit festgelegten Zielsymbolen).

Luis Mendo
quelle
4

JavaScript (ES6), 48 Byte

Nimmt Eingaben in der aktuellen Syntax vor (c)(n), wobei c eine Liste von Zeichen und n eine Ganzzahl ist.

Sicher nur für n <2 53 .

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

Probieren Sie es online!


JavaScript (ES6), 99 Byte

Mit Unterstützung für große ganze Zahlen

Nimmt Eingaben in der aktuellen Syntax vor (c)(a), wobei c eine Liste von Zeichen und a eine Liste von Dezimalstellen (als Ganzzahlen) ist.

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]:''

Probieren Sie es online!

Arnauld
quelle
4

x86-32-Bit-Computercode (32-Bit-Ganzzahlen): 17 Byte.

(Siehe auch die folgenden Versionen, einschließlich 16 Byte für 32-Bit- oder 64-Bit-Versionen mit einer DF = 1-Aufrufkonvention.)

Der Aufrufer übergibt Args in Registern, einschließlich eines Zeigers auf das Ende eines Ausgabepuffers (wie meine C-Antwort ; zur Begründung und Erläuterung des Algorithmus siehe). Die interne Funktion von glibc _itoatut dies , sodass sie nicht nur für Code-Golf entwickelt wurde. Die Arg-Passing-Register befinden sich in der Nähe von x86-64 System V, mit der Ausnahme, dass wir in EAX anstelle von EDX ein Arg haben.

Bei der Rückkehr zeigt EDI auf das erste Byte einer 0-terminierten C-Zeichenfolge im Ausgabepuffer. Das übliche Rückgabewertregister ist EAX / RAX. In der Assemblersprache können Sie jedoch jede für eine Funktion geeignete Aufrufkonvention verwenden. ( xchg eax,ediAm Ende würde 1 Byte hinzufügen).

Der Anrufer kann eine explizite Länge berechnen, wenn er möchte buffer_end - edi. Ich glaube aber nicht, dass wir es rechtfertigen können, das Abschlusszeichen wegzulassen, wenn die Funktion nicht tatsächlich beide Start- + Endzeiger oder Zeiger + Länge zurückgibt. Das würde in dieser Version 3 Bytes einsparen, aber ich halte es nicht für vertretbar.

  • EAX = n = zu decodierende Zahl. (For idiv. Die anderen Argumente sind keine impliziten Operanden.)
  • EDI = Ende der Ausgangspuffer (64-Bit - Version noch Verwendungen dec edi, so muss in dem niedrigen 4GiB sein)
  • ESI / RSI = Nachschlagetabelle, auch bekannt als LUT. nicht verstaut.
  • ECX = Länge der Tabelle = Basis. nicht verstaut.

nasm -felf32 ascii-compress-base.asm -l /dev/stdout | cut -b -30,$((30+10))- (Hand bearbeitet, um Kommentare zu verkleinern, Zeilennummerierung ist seltsam.)

   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

Es ist überraschend , dass die einfachste Version mit grundsätzlich keine Geschwindigkeit / Größe Kompromissen ist die kleinste, aber std/ cldKosten 2 Bytes zu verwenden , stosbin absteigender Reihenfolge zu gehen und immer noch dem gemeinsame DF = 0 Aufrufkonvention folgen. (Und STOS wird nach dem Speichern dekrementiert , wobei der Zeiger beim Beenden der Schleife ein Byte zu niedrig zeigt, was uns zusätzliche Bytes zum Umgehen kostet.)

Versionen:

Ich fand 4 signifikant unterschiedliche Implementierungstricks (mit einfachem movLaden / Speichern (oben), mit lea/ movsb(ordentlich, aber nicht optimal), mit xchg/ xlatb/ stosb/ xchgund einem, der mit einem überlappenden Anweisungs-Hack in die Schleife eintritt. Siehe Code unten) . Das letzte muss 0in der Nachschlagetabelle nachgestellt werden , damit es als Abschlusszeichen für die Ausgabezeichenfolge kopiert werden kann. Daher zähle ich das als +1 Byte. Abhängig von 32/64-Bit (1 Byte incoder nicht) und der Annahme, dass der Aufrufer DF = 1 ( stosbabsteigend) oder was auch immer setzt, sind verschiedene Versionen (gebunden für) am kürzesten.

Wenn DF = 1 in absteigender Reihenfolge gespeichert wird, gewinnt xchg / stosb / xchg, aber der Anrufer möchte das oft nicht. Es fühlt sich an, als würde man dem Anrufer die Arbeit auf eine schwer zu rechtfertigende Weise überlassen. (Im Gegensatz zu benutzerdefinierten Arg-Passing- und Return-Value-Registern, die einen asm-Aufrufer normalerweise keinen zusätzlichen Arbeitsaufwand verursachen.) Im 64-Bit-Code funktioniert cld/ scasbas jedoch so inc rdi, dass der Ausgabezeiger nicht auf 32-Bit gekürzt wird, was manchmal der Fall ist Es ist unpraktisch, DF = 1 in 64-Bit-Bereinigungsfunktionen beizubehalten. . (Zeiger auf statischen Code / Daten sind 32-Bit-Dateien in x86-64-Nicht-PIE-Programmen unter Linux und immer in Linux-x32-ABI. In einigen Fällen kann daher eine x86-64-Version mit 32-Bit-Zeigern verwendet werden.) Dieses Zusammenspiel macht es interessant, verschiedene Anforderungskombinationen zu betrachten.

  • IA32 mit einer DF = 0 bei Eingabe / Ausgabe-Aufrufkonvention: 17B ( nostring) .
  • IA32: 16B (mit einer DF = 1-Konvention: stosb_edx_argoder skew) ; oder mit eingehendem DF = nicht kümmern, lassen Sie es gesetzt: 16 + 1Bstosb_decode_overlap oder 17Bstosb_edx_arg
  • x86-64 mit 64-Bit-Zeigern und einer DF = 0 bei der Eingabe / Ausgabe-Aufrufkonvention: 17 + 1 Byte ( stosb_decode_overlap) , 18B ( stosb_edx_argoder skew)
  • x86-64 mit 64-Bit-Zeigern, andere DF-Verarbeitung: 16B (DF = 1 skew) , 17B ( nostringmit DF = 1 scasbanstelle von dec). 18B ( stosb_edx_argErhalt von DF = 1 mit 3 Byte inc rdi).

    Oder wenn wir zulassen, dass ein Zeiger auf 1 Byte vor der Zeichenfolge 15B ( stosb_edx_argohne das incam Ende) zurückgegeben wird. Alles bereit, erneut aufzurufen und einen weiteren String mit einer anderen Basis / Tabelle in den Puffer zu erweitern ... Aber das wäre sinnvoller, wenn wir auch keinen Abschluss speichern würden 0, und Sie könnten den Funktionskörper in eine Schleife einfügen, das ist also wirklich ein separates Problem.

  • x86-64 mit 32-Bit-Ausgabezeiger, DF = 0-Aufrufkonvention: Keine Verbesserung gegenüber 64-Bit-Ausgabezeiger, aber 18B ( nostring) wird jetzt verwendet.

  • x86-64 mit 32-Bit-Ausgabezeiger: Keine Verbesserung gegenüber den besten 64-Bit-Zeigerversionen, also 16B (DF = 1 skew). Oder DF = 1 setzen und es lassen, 17B für skewmit stdaber nicht cld. Oder 17 + 1B für stosb_decode_overlapmit inc ediam Ende anstelle von cld/ scasb.

Mit einer DF = 1-Aufrufkonvention: 16 Byte (IA32 oder x86-64)

Benötigt DF = 1 am Eingang, lässt es gesetzt. Zumindest funktionsbezogen kaum plausibel . Funktioniert genauso wie die obige Version, aber mit xchg, um den Rest in / aus AL vor / nach XLATB (Tabellensuche mit R / EBX als Basis) und STOSB ( *output-- = al) zu bekommen.

Bei einem normalen DF = 0 am Eintritts- / Austritt Konvention, die std/ cld/ scasbVersion ist 18 Bytes für 32 und 64-Bit - Code, und ist 64-bit sauber (Arbeiten mit einem 64-Bit - Ausgangs - Hinweiszeigern).

Beachten Sie, dass sich die Eingabeargs in verschiedenen Registern befinden, einschließlich RBX für die Tabelle (für xlatb). Beachten Sie auch, dass diese Schleife mit dem Speichern von AL beginnt und mit dem letzten noch nicht gespeicherten Zeichen endet (daher movdas Ende). Die Schleife ist also relativ zu den anderen "schief", daher der Name.

                            ;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

Eine ähnliche, nicht verzerrte Version übersteuert EDI / RDI und behebt es dann.

                            ; 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

Ich habe eine alternative Version davon mit lea esi, [rbx+rdx]/ movsbals innerem Schleifenkörper ausprobiert . (RSI wird bei jeder Iteration zurückgesetzt, RDI wird jedoch dekrementiert.) Aber es kann nicht xor-zero / stos als Abschlusszeichen verwenden, daher ist es 1 Byte größer. (Und es ist nicht 64-Bit-sauber für die Nachschlagetabelle ohne ein REX-Präfix auf der LEA.)


LUT mit expliziter Länge und einem 0-Terminator: 16 + 1 Byte (32 Bit)

Diese Version setzt DF = 1 und belässt es so. Ich zähle das zusätzliche LUT-Byte, das als Teil der Gesamtbytezahl benötigt wird.

Der coole Trick dabei ist , dieselben Bytes auf zwei verschiedene Arten dekodieren zu lassen . Wir fallen in die Mitte der Schleife mit Rest = Basis und Quotient = Eingangsnummer und kopieren den 0-Terminator an die richtige Stelle.

Beim ersten Durchlauf der Funktion werden die ersten 3 Bytes der Schleife als High-Bytes eines Disp32 für eine LEA verbraucht. Diese LEA kopiert die Basis (Modul) nach EDX und idiverzeugt den Rest für spätere Iterationen.

Das 2. Byte von idiv ebpist FDder Opcode für den stdBefehl, den diese Funktion benötigt, um zu funktionieren. (Dies war eine glückliche Entdeckung. Ich hatte dies mit divfrüher betrachtet, was sich von der idivVerwendung der /rBits in ModRM unterscheidet. Das 2. Byte von div epbdecodiert als cmc, was harmlos, aber nicht hilfreich ist. Aber mit idiv ebpkönnen wir tatsächlich das stdvon oben entfernen der Funktion.)

Beachten Sie, dass die Eingangsregister wieder einen Unterschied darstellen: EBP für die Basis.

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

Dieser überlappende Decodiertrick kann auch verwendet werden mit cmp eax, imm32: Es wird nur 1 Byte benötigt, um effektiv 4 Byte vorwärts zu springen, nur um Flags zu blockieren. (Dies ist für die Leistung auf CPUs, die Befehlsgrenzen im L1i-Cache markieren, schrecklich.)

Aber hier verwenden wir 3 Bytes, um ein Register zu kopieren und in die Schleife zu springen. Das würde normalerweise 2 + 2 (mov + jmp) dauern und uns in die Schleife direkt vor dem STOS anstatt vor dem XLATB springen lassen. Aber dann bräuchten wir eine separate Geschlechtskrankheit, und das wäre nicht sehr interessant.

Probieren Sie es online! (mit einem _startAnrufer, der sys_writedas Ergebnis verwendet)

Für das Debuggen ist es am besten, es unter auszuführen straceoder die Ausgabe zu verhexen, damit Sie überprüfen können, ob sich \0an der richtigen Stelle ein Abschlusszeichen befindet und so weiter. Aber Sie können sehen, dass dies tatsächlich funktioniert, und AAAAAACHOOfür eine Eingabe von produzieren

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

(Eigentlich xxAAAAAACHOO\0x\0\0..., weil wir von 2 Bytes früher in dem zu einer festen Länge Puffer aus Dumping. So wir , dass die Funktion sehen , schrieb den Bytes es sollte zu und tat nicht Schritt auf jedem Bytes sollte es nicht haben. Die Der an die Funktion übergebene Startzeiger war das vorletzte xZeichen, gefolgt von Nullen.)

Peter Cordes
quelle
3

Gelee , 4 Bytes

ṙ1ṃ@

Probieren Sie es online!

ist buchstäblich ein eingebautes dafür. Die anderen drei Bytes sind für Jellys einseitige Indizierung verantwortlich.

Mr. Xcoder
quelle
Warum hat Jelly aus Neugier sogar die eingebaute " Basis-Dekomprimierung; konvertiere x in Basislänge (y) und indexiere dann in y "? Ist dies für ganz außergewöhnliche Fälle der Fall, in denen die Basis, in die Sie konvertieren möchten, und die Länge einer Zeichenfolge / Ganzzahl / Liste gleich sind? Wenn ich danach suche, kann ich damit nur drei Antworten finden: 1 ; 2 ; 3 . Irgendwie ein seltsamer Bestandteil alltäglicher Code-Golf-Herausforderungen. : S
Kevin Cruijssen
3
@KevinCruijssen ist sehr nützlich, wenn Sie beispielsweise N in Hexadezimal mit Hexadezimalbuchstaben anstelle einer Liste von Zahlen konvertieren möchten .
Mr. Xcoder
@ KevinCruijssen Es ist eine Komprimierungsmethode für Zeichenfolgen. Im ersten Beispiel ist die gewünschte Zeichenfolge “sspspdspdspfdspfdsp”, aber mit “çƥ÷£ḟ’ṃ“spdf”¤Ihnen sparen Sie sechs Bytes. Es ist besonders nützlich bei
Jellys
3

Python 2 , 49 48 Bytes

-1 Byte danke an Jo King

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

Probieren Sie es online!

Alternative Version (wird bei großen Zahlen nicht beendet), 45 43 Bytes

-2 Bytes dank Jo King

f=lambda n,s:s*n and f(n/len(s),s)+(s*n)[n]

Probieren Sie es online!

Stange
quelle
3

Kohle , 3 1 Bytes

θη

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Bearbeiten: 2 Bytes dank nur @ ASCII gespeichert. Vorherige Version, bevor das Builtin hinzugefügt wurde, 8 Bytes:

⭆↨θLη§ηι

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

    η       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
Neil
quelle
Eigentlich soll es schon klappen, aber ich habe es offenbar wieder versaut> _>
Nur ASCII
Außerdem würde es eigentlich sein 1 Byte : P (es derzeit allerdings kaputt ist, so bin ich nicht die Nummer und String - Array als Argumente verwendet) (auch, ich frage mich , wie (un) nützlich implizite Eingabe)
ASCII-only
@ Nur ASCII Meinst du nicht "1 Byte" (siehe deine -vl-Ausgabe ;-) Außerdem scheint die implizite Eingabe in Charcoal fast unbrauchbar zu sein, außer bei Herausforderungen wie diesen.
Neil,
1
@ Nur ASCII Mehrere "Bytes" anstelle eines einzelnen "Bytes" ist das, was Neil meint. ;) Was deine 1-Byte-Antwort betrifft, warum das durchgestrichene θη? Sieht ein bisschen verwirrend aus. Warum nicht einfach komplett entfernen und gehen ?
Kevin Cruijssen
1
@Nit Ich habe zweimal nachgesehen und das eingebaute Programm wurde hinzugefügt, bevor die Frage gestellt wurde, aber ich hatte es nicht bemerkt, weil es einen Fehler hatte.
Neil
3

D 112 Bytes

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;}

Probieren Sie es online!

Dies ist eine Portierung der C ++ - Antwort von HatsuPointerKun

Der Aufrufstil ist u(ulong(n), to!(char[])(b)), wo nund bsind die linken und rechten Argumente

D bestimmte Sachen

Leider müssen wir Import std.convüber keine Typkonvertierungen zu tun , sehr grundlegende Typumwandlung.

Unter Verwendung des Golfy Template - System und gibt die Funktion die erforderlichen Typen (die , warum es ist nicht nur telefonieren ist u(n,b)), können wir das Auftreten von verkürzen char[]und ulongzu 1Byte jedem, wenn innerhalb f der Funktion.

D initialisiert unsere Typen für uns, C t;ist also die Abkürzung fürC t=cast(char[])([])

to!Ckonvertiert die Ganzzahl n%lin ein Zeichenarray (unter Verwendung von Codepunkten) und ~ist Verkettung

foreach(ref c;t)ist wie die for(... : ...)Schleife von C ++ , aber etwas länger. refist wie &, es wird cals per Referenz kopiert behandelt (dh wir können modifizieren t). Zum Glück, D folgern den Typen cohne jedes Schlüsselwort Bezeichnen Typen.

Zacharý
quelle
3

C ++, 150 144 Bytes, uint64Eingabe

-6 Bytes dank 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;}

Die Verwendung einer Variablen zum Speichern der Größe würde den Bytecount um 1 erhöhen

So rufen Sie die Funktion auf:

u(2740, "|_")

Erstens die Zahl, zweitens die Zeichenkette (char array)

Testfälle:

std::cout << u(2740, "|_") << '\n' << u(698911, "chao") << '\n';
return 0;
HatsuPointerKun
quelle
1
3 Bytes scheren: Sie müssen nicht den Raum benötigen nach #include, können Sie ändern ;;einfach ;und '0'kann einfach sein48
Zachary
1
Die while-Schleife könnte auch eine forSchleife sein:for(;n;n/=b.size())t=std::to_string(n%b.size())+t;
Zacharý
@ceilingcat, ich habe vergessen, dass sich b.size()das in dieser Schleife nicht ändert.
Zacharý
@ceilingcat Das würde den bytecount um 1 erhöhen, anstatt ihn zu senken
HatsuPointerKun
2

Zweig, 66 Bytes

Erstellt ein macro, das importin eine Vorlage eingefügt werden muss .

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

Werte erwartet:

Für die ersten Argumente ( n):

  • Nummer
  • Zeichenfolge

Für das zweite Argument ( c):

  • Array von Zahlen
  • Array von Zeichenfolgen

Wie benutzt man:

  • Erstellen Sie eine .twigDatei
  • Hinzufügen {% import 'file.twig' as uncompress %}
  • Rufen Sie das Makro auf uncompress.d()

Ungolfed (nicht funktionsfähig):

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


Sie können diesen Code unter https://twigfiddle.com/54a0i9 testen

Ismael Miguel
quelle
2

Pyth, 9 8 7 Bytes

s@LQjEl

Sparte ein Byte dank hakr14 und ein weiteres dank Mr. Xcoder.
Probieren Sie es hier aus

Erläuterung

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.

quelle
Speichern Sie ein Byte durch den Austausch m@Qdmit@LQ
hakr14
Speichern Sie ein Byte durch den Ersatz vzmit E.
Mr. Xcoder
2

C89, signiert mit eingeschränktem Bereich int n, 64 53 Byte

  • Changelog: nimm ein char **outund ändere es, anstatt ein zu nehmen und zurückzugebenchar *

Nimmt die Zahl als ein int, die Nachschlagetabelle als Array + Länge.
Die Ausgabe wird in a geschrieben char *outbuf. Der Aufrufer übergibt (als Referenz) einen Zeiger an das Ende des Puffers. Die Funktion ändert diesen Zeiger so, dass er bei der Rückgabe auf das erste Byte der Zeichenfolge zeigt.

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

Dies ist C89 und funktioniert auch bei aktivierter Optimierung ordnungsgemäß. Das heißt, es hängt nicht vom -O0Verhalten von gcc ab , wenn eine nicht leere Funktion beendet ist oder eine andere UB vorliegt.

Das Übergeben eines Zeigers an das Ende eines Puffers ist normal für eine optimierte int-> string-Funktion, z. B. die interne_itoa Funktion von glibc . In dieser Antwort finden Sie eine detaillierte Erklärung zum Aufteilen einer Ganzzahl in Ziffern mit einer Div / Mod-Schleife, wie wir es hier tun, sowohl in C als auch in x86-64 asm. Wenn die Basis eine Potenz von 2 ist, können Sie die MSD-Ziffern zuerst verschieben / maskieren, ansonsten ist die niedrigstwertige Ziffer zuerst (mit Modulo) die einzige gute Option.

Probieren Sie es online! . Ungolfed-Version:

/* 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;
}

In dieser expliziten Länge Version, ist die Eingabe ein , char table[]die sie nicht mit einem Abschluss 0 Byte benötigen, weil wir es nie als String behandeln. Es könnte eine sein, int table[]für die wir uns interessieren. C hat keine Container, die ihre eigene Länge kennen. Daher ist Zeiger + Länge der normale Weg, ein Array mit einer Größe zu übergeben. Also wählen wir das, anstatt es zu müssen strlen.

Die maximale Puffergröße beträgt ungefähr sizeof(int)*CHAR_BIT + 1, daher ist sie klein und konstant für die Kompilierungszeit. (Wir verwenden so viel Platz mit base = 2 und allen auf 1 gesetzten Bits.) ZB 33 Bytes für 32-Bit-Ganzzahlen, einschließlich des 0Abschlusszeichens.


C89, signiert int, Tabelle als implizite C-Zeichenfolge, 65 Byte

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

Dies ist das gleiche, aber die Eingabe ist eine implizite Zeichenfolge, sodass wir die Länge selbst ermitteln müssen.

Peter Cordes
quelle
2

Bash + Core-Dienstprogramme , 49 Byte

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

Probieren Sie es online!

Kommentare / Erklärung

Dies nimmt Befehlszeilenargumente als Eingabe (die Zahl in Basis 10, dann eine einzelne Zeichenfolge mit der Liste der Zeichen) und gibt sie an stdout aus. Sonderzeichen wie Leerzeichen, Zeilenumbruch, usw. können (zum Beispiel in Oktalschreibweise eingegeben werden \040für einen Raum) oder \nfür eine neue Zeile, \tfür Reiter, oder jede andere Escape - Sequenz , dass echo -eund tridentisch interpretieren.

Ein Großteil der Bytes dient hier der Behandlung von Sonderzeichen und größeren Testfällen. Wenn ich nur nicht schreckliche Zeichen behandeln muss und die Zahlen klein sind (zum Beispiel der erste Testfall), reichen die folgenden 24 Bytes aus:

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

Dies verwendet die Parametererweiterung ${#2}, um die Anzahl der Zeichen in der Zeichenfolge abzurufen, erstellt ein DC-Programm für die Basiskonvertierung und sendet dann die konvertierte Zahl durch tr.

Dies behandelt jedoch keine Zeilenumbrüche, Leerzeichen oder Tabulatoren. Um mit Escape-Sequenzen umzugehen, ohne die Basis zu beeinflussen, zähle ich die Zeichen, wc -cnachdem ich die Escape-Zeichen mit interpretiert habe echo -en. Dies erweitert das Programm auf 38 Bytes:

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

Leider hat dc eine nervige "Funktion", bei der bei Ausgabe einer großen Zahl ein Zeilenumbruch mit einem Schrägstrich und einer Zeilenumbruchsequenz erfolgt, sodass die größeren Testfälle diese zusätzliche Ausgabe haben. Um es zu entfernen, leite ich die Ausgabe von DC durch tr -dc 0-9, um nicht numerische Zeichen zu entfernen. Und da sind wir.

Sophia Lechner
quelle
Ich wollte vorschlagen , um dc -e${#2}o$1p|tr 0-9 "$2"die Eingabe zu wörtlich zu nehmen , anstatt in \ Form entkommen , so dass es kann Leerzeichen verarbeiten, aber trkeine Möglichkeit habe, nicht behandeln -als einen Bereich Zeichen, zum Beispiel. Wenn sich die Eingabe -nicht an einem Ende der Zeichenfolge befindet, wird sie unterbrochen. Vielleicht kannst du verwenden sed "y/0123456789/$2/". Nein, ich denke nicht, GNU sedverlangt , dass beide Argumente ygleich lang sind, und es scheint, als würde es bei Newline ersticken.
Peter Cordes
2

APL (Dyalog Unicode) , 14 13 12 Bytes

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

Probieren Sie es online!

Infix implizite Funktion; kann den größten Testfall aufgrund der Gleitkommadarstellung nicht verarbeiten.

Gespeichert 1 2 Bytes dank @ Adám!

13 Bytes für die Header hinzugefügt: ⎕IO←0: I ndex O Rigin = 0 und ⎕FR←1287: F loat R ePresentation = 128 Bit. (Ich hatte vergessen, dass dies nicht zutrifft. )

Wie?

⊢⌷⍨∘⊂⊥⍣¯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.
J. Sallé
quelle
2

Attache , 17 Bytes

{_[_2&ToBase!#_]}

Probieren Sie es online!

Erläuterung

{_[_2&ToBase!#_]}
{               }  ?? anonymous lambda; input: _ = dictionary, _2 = encoded
   _2&ToBase       ?? convert _2 to base
            !#_    ?? ... Size[_]
 _[            ]   ?? and take those members from the dictionary
Conor O'Brien
quelle
1

Canvas , 7 Bytes

L┬{╵⁸@p

Probieren Sie es hier aus!

Einfache Implementierung:

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

Der eingegebene Zeichensatz kann auch eine Zeichenfolge sein, solange er keinen Zeilenumbruch enthält, da Canvas keinen Zeilenumbruch enthält und ihn automatisch in ein 2D-Objekt konvertiert.

dzaima
quelle
1

Stax , 6 5 Bytes

n%|E@

Führen Sie es aus und debuggen Sie es

Erläuterung:

n%|E@ Full program, implicit input in order list, number
n%    Copy the list to the top and get its length
  |E  Convert the number to that base
    @ Map: index
wastl
quelle
1

SOGL V0.12 , 10 Bytes

l;A─{IaWp}

Probieren Sie es hier aus!

Ziemlich lang, wenn man bedenkt, dass die Idee so ziemlich in der Sprache umgesetzt ist: hier eintreten

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

gibt mit dieser Methode einen komprimierten String aus.

dzaima
quelle
1

Stax , 2 Bytes

:B

Führen Sie es aus und debuggen Sie es

:Bist eine Anweisung in stax, die dies tut. Normalerweise wird eine "Zeichenfolge" * anstelle eines Arrays von "Zeichenfolgen" verarbeitet. Am Ende bedeutet dies, dass die Ausgabe ein Array von Einzelzeichen-Arrays ist. Die Ausgabe flacht jedoch implizit ab.

* Stax hat eigentlich keinen String-Typ. Text wird durch ganzzahlige Arrays von Codepunkten dargestellt.

rekursiv
quelle
Huh, ich habe diesen Befehl nie bemerkt ...
Wastl
Es gibt eine Menge. Ich habe stax einmal eine Anweisung hinzugefügt, die es bereits gab und die ich gerade vergessen hatte. (Array ist nicht absteigend?)
rekursive
1

J , 12 Bytes

]{~#@]#.inv[

Wie?

      #.inv    convert
           [   the left argument (the number)      
   #@]         to base the length of the right argument (the list of characters)    
  {~           and use the digits as indices to
]              the list of characters        

Probieren Sie es online!

Galen Ivanov
quelle
1

C (gcc) , 110 Bytes

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;}

Probieren Sie es online!

Beschreibung:

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
LambdaBeta
quelle
1
Wenn Sie am Ende eines Puffers beginnen und rückwärts arbeiten, können Sie dies vermeiden sprintf. Meine C-Version hat 53 Bytes , wobei der Ausgabepuffer vom Aufrufer bereitgestellt wird. Sie können einen strcpyam Ende ausführen, wenn Sie die Bytes an den Anfang eines Puffers kopieren möchten.
Peter Cordes
Das ist genial Es ist mir egal, ob es sich um ein umständliches E / A-Format handelt. Peinliche I / O ist C Anspruch auf Ruhm! Gut gemacht, ich würde empfehlen, das in den C-Tipps-Post zu setzen.
LambdaBeta
Hat eine Antwort auf Tipps zum Golfen in C veröffentlicht , in der die Technik erklärt und begründet wird.
Peter Cordes
1

CJam , 11 Bytes

liq_,@\b\f=

Probieren Sie es online! Übernimmt die Eingabe als Zahl, dann als Newline und dann als Zeichen in der ASCII-Grafik.

Erläuterung

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
NinjaBearMonkey
quelle
Da "IO ist flexibel", denke ich, dass Sie das liqam Anfang loswerden können , und das spart Ihnen 3 Bytes!
Chrom
1

JavaScript, 39 Bytes

Hafen von Rods Python-Lösung .

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

Probieren Sie es online aus

Zottelig
quelle
Funktioniert nur mit nbis zu 64-Bit, oder? (In Python sind Ganzzahlen mit willkürlicher Genauigkeit integriert, aber JS-Zahlen sind natürlich doubleGleitkommazahlen mit Genauigkeit, die in Ganzzahlen konvertiert werden können.) Scheint nicht für die größeren Testfälle in der Frage zu funktionieren, wie 1928149325670647244912100789213626616560861130859431492905908574660758972167966. Oh, aber die Frage ermöglicht Antworten wie diese. Trotzdem sollte angemerkt werden.
Peter Cordes
1

SimpleTemplate , 86 Byte

Wow, das war eine große Herausforderung!

Dies wurde durch den fehlenden direkten Zugriff auf bestimmte Indizes erschwert, wenn der Index eine Variable ist.
Ein Fehler hat es auch länger gemacht, da die Werte in einer Variablen gespeichert werden mussten.

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

Werte erwartet:

Das erste Argument ( argv.0) kann sein:

  • Eine ganze Zahl
  • Eine Zeichenfolge mit Zahlen
  • Ein Array von ganzen Zahlen

Das zweite Argument ( argv.1) kann sein:

  • Ein Faden
  • Eine Anordnung

Wie funktioniert das?

Es funktioniert so:

  • Durchläuft die als erstes Argument übergebene Zahl / Zeichenfolge
  • Legt fest, dass die Variable Cein Array ist, das Folgendes enthält:
    • Der vorherige Wert C
    • Die Saite "{@echoA."
    • Der Wert der Schleife
    • Die Saite "}"
  • Schließt sich alles zusammen (PHP mit joinFunktion)
    Daraus ergibt sich, zum Beispiel, Centhält"{@echoA.0}{@echoA.1}..."
  • Wertet das Ergebnis von aus C

Ungolfed:

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

Sie können diesen Code unter https://ideone.com/NEKl2q ausprobieren


Optimales Ergebnis

Wenn es keine Fehler gäbe, wäre dies das beste Ergebnis unter Berücksichtigung der Einschränkungen (77 Bytes):

{@eachargv.0}{@setC C,"{@echoargv.1.",_,"}"}{@calljoin intoC"",C}{@/}{@evalC}
Ismael Miguel
quelle