base-n番号からのASCIIアート圧縮解除


24

これは、Magic Octupus Urnによる05AB1Eの回答に触発されました。

2つの引数、正の整数と文字列/文字のリストが与えられた場合:

  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。つまり、最小のベースはバイナリで、最大のベースは10進数です(ここでは厄介な文字はありません
  • 標準的な抜け穴は禁止されています
  • 言語がより大きなテストケースを処理できない場合でも、お気軽に回答してください。

これはであるため、各言語の最短コードが優先されます。(すべてのゴルフ言語には1バイトのビルトインが用意されています。)



3
D'awwh、私は光栄に思います。05AB1E ascii-artはしばらく前からお気に入りでした。
魔法のタコ

新しいチャレンジを作成できます。配列内の文字の順列を見つけて、数を最小化してください:)
mazzy

回答:


8

05AB1E7 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ありがとう。¹sè今は自分のことを考えていなかったとは信じられません。(この場合、?に変更するとJ同じ出力が得られることを知っていました。)
ケビンクルーイッセン

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バイト)「IOは柔軟です」
オリビエグレゴワール

String f(char[]a,int n){return n>0?f(a,n/a.length)+a[n%a.length]:"";}(69バイト)楽しみのために、再帰的なもの。
オリビエグレゴワール


5

Japt、2バイト

2番目の入力を配列または文字列として受け取ることができます。数値がJavaScriptの最大整数を超えているため、最後の2つのテストケースに失敗します。置換sìて、代わりに文字の配列を出力します。

sV

それを試してみてください


5

Haskell40 39バイト

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

オンラインでお試しください!

HaskellのIntタイプはに制限されているため9223372036854775807、これは大きな数値では失敗します。

ライコニのおかげで-1バイト。

非ゴルフ

(!) :: 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代わりに使用する良いアイデアmoddiv n(length l)バイトを保存します。
ライコニ


4

JavaScript(ES6)、48バイト

カリー化構文(c)(n)で入力を受け取ります。cは文字のリストで、nは整数です。

n <2 53に対してのみ安全です。

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

オンラインでお試しください!


JavaScript(ES6)、99バイト

大きな整数をサポート

カリー化構文(c)(a)で入力を受け取ります。cは文字のリストで、aは10進数のリスト(整数)です。

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バイト。

(32ビットまたは64ビットの16バイトを含む、DF = 1呼び出し規約を含む、以下の他のバージョンも参照してください。)

発信者はへのポインタを含むレジスタ内の引数渡し、エンド出力バッファの(のような私のCの答えを、正当化し、アルゴリズムの説明については、それを参照してください。) のglibcの内部_itoaこれを行い、それが単にコードゴルフのために考案していないので、。引数渡しレジスタは、EDXの代わりにEAXに引数があることを除いて、x86-64 System Vに近いです。

戻り時に、EDIは出力バッファー内の0で終わるC文字列の最初のバイトを指します。通常の戻り値レジスタはEAX / RAXですが、アセンブリ言語では、関数にとって便利な呼び出し規約を使用できます。(xchg eax,edi最後に1バイトを追加します)。

呼び出し元は、必要に応じて明示的な長さを計算できますbuffer_end - edi。しかし、関数が実際に開始+終了ポインターまたはポインター+長さの両方を返さない限り、ターミネーターを省略することを正当化できるとは思いません。このバージョンでは3バイト節約できますが、それが正当であるとは思いません。

  • EAX = n =デコードする数。(idiv。の場合、他の引数は暗黙的なオペランドではありません。)
  • EDI =出力バッファの終わり(64ビットバージョンはを引き続き使用するdec ediため、低4GiBでなければなりません)
  • ESI / RSI =ルックアップテーブル、別名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は保存後に減少、ポインターがループ終了時に1バイト低くなりすぎて、回避するために余分なバイトがかかります。)

バージョン:

4つの大幅に異なる実装のトリック(mov上記の単純なロード/ストアの使用、lea/ movsb(ニートだが最適ではない)の使用、xchg/ xlatb/ stosb/の使用xchg、オーバーラップ命令ハックでループに入るもの)を思い付きました。 。最後は0、出力文字列ターミネータとしてコピーするためにルックアップテーブルの末尾が必要なので、+ 1バイトとしてカウントしています。32/64ビット(1バイトincかどうか)、および呼び出し元がDF = 1(stosb降順)を設定できるかどうかに応じて、異なるバージョンが最短(拘束)になります。

DF = 1を降順で格納すると、xchg / stosb / xchgに勝ちますが、呼び出し側はしばしばそれを望まないでしょう。正当化するのが難しい方法で呼び出し元に作業をオフロードするように感じます。(通常、asm呼び出し元に余分な作業を必要としないカスタムの引数渡しおよび戻り値レジスタとは異なります。)しかし、64ビットコードでは、cld/ scasbはとして機能しinc rdi、出力ポインタを32ビットに切り捨てないため、 64ビットクリーン関数でDF = 1を保持するのは不便です。。(静的コード/データへのポインターは、Linux上のx86-64非PIE実行可能ファイルでは32ビットであり、常にLinux x32 ABIであるため、32ビットポインターを使用するx86-64バージョンが使用できる場合があります。)この相互作用により、要件のさまざまな組み合わせを見ることができます。

  • エントリー/出口呼び出し規約でDF = 0を使用したIA32:17B(nostring
  • IA32:16B(DF = 1の規則:stosb_edx_argまたはskew ; または、着信DF = dontcareを使用して、16 + 1Bstosb_decode_overlapまたは17Bを設定したままにしますstosb_edx_arg
  • 64ビットポインターを使用するx86-64、およびエントリ/出口呼び出し規約のDF =stosb_decode_overlap 0:17 + 1バイト(、18B(stosb_edx_argまたはskew
  • 64ビットポインターを備えたx86-64、その他のDF処理:16B(DF = 1 skew、17B(nostringDF = 1で、scasb代わりに使用dec)。18B(stosb_edx_arg3バイトでDF = 1を保持inc rdi)。

    または、文字列の1バイト前のポインターを返すことを許可する場合、15B(末尾stosb_edx_argなしinc)。 すべてを再度呼び出して、別の文字列を異なるベース/テーブルのバッファに展開するように設定します... しかし、終端0も保存しない場合、それはより理にかなっており、ループ内に関数本体を置くことができます。別の問題。

  • 32ビット出力ポインターを備えたx86-64、DF = 0呼び出し規約:64ビット出力ポインターよりも改善はありませんが、18B(nostring)になりました。

  • 32ビット出力ポインターを備えたx86-64:最高の64ビットポインターバージョンと比べて改善がないため、16B(DF = 1 skew)。または、DF = 1を設定してそのままにしておくには、17Bでskewwithでstd、notではありませんcld。または、末尾に/の代わりに17 + 1Bをstosb_decode_overlap使用inc ediします。cldscasb

DF = 1呼び出し規約の場合:16バイト(IA32またはx86-64)

入力時にDF = 1が必要で、設定されたままにします。 少なくとも機能ごとに、ほとんど妥当と思われます。上記のバージョンと同じことを行いますが、xchgを使用して、XLATB(ベースとしてR / EBXを使用したテーブル検索)およびSTOSB(*output-- = al)の前後にALの残りを取得または削除します。

エントリ/出口規則の通常のDF = 0ではstd/ cld/ scasbバージョンは32および64ビットコードで18バイトであり、64ビットクリーンです(64ビット出力ポインターで動作します)。

入力引数は、テーブルのRBX(for 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バイト大きくなります。(また、LEAにREXプレフィックスがないルックアップテーブルでは、64ビットクリーンではありません。)


明示的な長さ 0ターミネータを持つLUT :16 + 1バイト(32ビット)

このバージョンはDF = 1に設定し、そのままにします。合計バイト数の一部として必要な追加のLUTバイトをカウントしています。

ここでのクールなトリックは、同じバイトで2つの異なる方法をデコードすることです。ループの真ん中に残り= baseとquotient =入力番号を入れて、0ターミネーターを所定の位置にコピーします。

関数を初めて使用すると、ループの最初の3バイトがLEAのdisp32の上位バイトとして消費されます。そのLEAはベース(モジュラス)をEDXにコピーし、idiv後の反復のために残りを生成します。

の2番目のバイトはidiv ebpですFD。これは、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バイトを効果的に前方にジャンプし、フラグを壊します。(これは、L1iキャッシュ(BTW)の命令境界をマークするCPUのパフォーマンスにとってはひどいです。)

しかし、ここでは、レジスタをコピーしてループにジャンプするために3バイトを使用しています。通常は2 + 2(mov + jmp)を必要とし、XLATBの前ではなく、STOSの直前にループにジャンプできます。しかし、その後、別のSTDが必要になり、あまり面白くないでしょう。

オンラインでお試しください!(結果_startで使用する呼び出し元とsys_write

デバッグを行うにstraceは、出力の下で実行するか、出力を16進ダンプするのが最善です\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バイト前から固定長にダンプしているため、関数が想定されたバイトを書き込み、必要のないバイトを踏まなかったことがわかります。関数に渡される開始ポインターは最後から2番目のx文字で、その後にゼロが続きました。)


3

ゼリー、4バイト

ṙ1ṃ@

オンラインでお試しください!

文字通りこのための組み込みです。他の3バイトは、Jellyの1ベースのインデックス作成を説明します。


好奇心から、Jellyには組み込みの基本解凍; xを基本length(y)に変換してから、yにインデックスを付ける」という理由さえあります。変換するアリと文字列/整数/リストの長さが等しい非常に例外的な場合ですか?私はそれを検索すると、私はそれを使用して、3つの答えを見つけることができます:12 ; 。ちょっと変わったビルトインが毎日コードゴルフに挑戦しています。:S
ケビンクルーッセン

3
@KevinCruijssenたとえば、数字のリストの代わりに16進文字を使用してNを16進数に変換する場合に非常に便利です。
Mr Xcoder

@KevinCruijssen文字列の圧縮方法です。最初の例では“sspspdspdspfdspfdsp”、必要な文字列はですが、“çƥ÷£ḟ’ṃ“spdf”¤6バイト節約できます。これは、ゼリーのベース250番号で特に役立ちます
ディルナン


3

3 1バイト

θη

オンラインでお試しください!リンクは、コードの詳細バージョンです。編集:@ASCIIのみのおかげで2バイト保存されました。組み込みが追加される前の以前のバージョン、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バイト:(iの引数として数値と文字列の配列を使用していないので、それは現在、しかし破損)P(また、私はどのように(UN)便利な暗黙の入力があるだろう)
ASCIIのみ

@ ASCII-only「1バイト」という意味ではありません(-vl出力を参照してください;-)また、このようなチャレンジを除いて、Charcoalでは暗黙的な入力はほとんど役に立たないようです。
ニール

1
@ASCIIのみ単数形の「バイト」ではなく複数の「バイト」がニールの意味です。;)1バイトの回答については、なぜ消されたのθηですか?少しわかりにくいです。なぜそれを完全に削除して去らないのですか?
ケビンクルーッセン

1
@Nit私はダブルチェックし、質問が尋ねられる前にビルトインが追加されていましたが、バグがあったので気がつきませんでした。
ニール

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

オンラインでお試しください!

これはHatsuPointerKunのC ++回答の移植版です

呼び出しスタイルはu(ulong(n), to!(char[])(b))、ここでnおよびbは左右の引数です

D特定のもの

悲しいことに、非常に基本的な型変換をstd.conv超える型変換を行うには、インポートする必要があります。

(それを呼び出すことだけではない理由であるgolfyテンプレートシステムを使用して、関数に必要な種類を与えるu(n,b))、我々はの出現短縮できるchar[]ulongする1、各バイトをするとき関数Fの内部。

Dは型を初期化するC t;ため、C t=cast(char[])([])

to!Cn%l(コードポイントを使用して)整数を文字配列に変換し、~連結します

foreach(ref c;t)C ++のfor(... : ...)ループに似ていますが、もう少し長くなります。refのようなもので&c参照によるコピーとして処理します(つまり、変更できますt)。幸いにも、Dは、の種類を推測cすることなく、任意のキーワードを表すタイプ。



3

C ++、150 144バイト、uint64入力

ザカリーのおかげで-6バイト

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

変数を使用してサイズを格納すると、バイトカウントが1増加します

関数を呼び出すには:

u(2740, "|_")

最初は数値、2番目は文字列(char配列)

テストケース:

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

1
図3は、オフに剃るバイト:あなたは後にスペースを必要としない#includeあなたが変更することができ、;;ちょうどに;、そして'0'ちょうどすることができ48
ザカリー

1
また、whileループは、可能性がforループ:for(;n;n/=b.size())t=std::to_string(n%b.size())+t;
ザカリー

@ceilingcat、b.size()そのループで変わらないことを忘れていました。
ザカリー

@ceilingcatこれは、バイト数を減らすのではなく、1増やすことです
HatsuPointerKun

2

小枝、66バイト

テンプレートに編集するmacro必要があるを作成しimportました。

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

期待される値:

最初の引数(n)の場合:

  • ひも

2番目の引数(c)の場合:

  • 数字の配列
  • 文字列の配列

使い方:

  • .twigファイルを作成する
  • 追加する {% import 'file.twig' as uncompress %}
  • マクロを呼び出す uncompress.d()

非ゴルフ(非機能):

{% 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に1バイト、Mr。Xcoderにもう1つ感謝します。
ここで試してみてください

説明

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 n64 53バイト

  • 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、非void関数の終わりから落ちるとき、または他のUBを持つとき、gccの動作に依存しません。

glibcのinternal_itoaなどの最適化されたint-> string関数では、バッファーの最後にポインターを渡すのは正常です。Cおよびx86-64 asmでここで行っているように、整数をdiv / modループで数字に分割する詳細な説明については、この回答を参照してください。基数が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;
}

この明示的な長さのバージョンでは、入力は文字列として扱われないため、終端の0バイトを必要char table[]としない aです。それはint table[]私たちが気にするすべてのためかもしれません。Cには、独自の長さを知っているコンテナーがないため、ポインター+長さは、サイズを持つ配列を渡す通常の方法です。したがって、必要な代わりにそれを選択しますstrlen

最大バッファサイズは約sizeof(int)*CHAR_BIT + 1ですので、小さく、コンパイル時の定数です。(base = 2とすべてのビットを1に設定してこのスペースを使用します。)例えば、0ターミネーターを含む32ビット整数の場合は33バイト。


int暗黙の長さのC文字列としてのC89、signed 、テーブル、65バイト

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

これも同じですが、入力は暗黙の長さの文字列なので、自分で長さを見つける必要があります。


2

Bash +コアユーティリティ、49バイト

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

オンラインでお試しください!

コメント/説明

これは、コマンドライン引数を入力(10進数の数、次に文字のリストを含む単一の文字列)として受け取り、stdoutに出力します。スペースや改行などの特殊文字は、8進表記(\040スペースなど)で入力するか\n、改行、\tタブ、または同じようecho -etr解釈されるその他のエスケープシーケンスで入力できます。

ここでのバイトの多くは、特殊文字とより大きなテストケースを処理するためのものです。ひどい文字を処理する必要がなく、数字が小さい場合(たとえば、最初のテストケース)、次の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には厄介な「機能」があり、大量の出力を行う場合は、スラッシュ+改行シーケンスで改行するため、大きなテストケースではこの余分な出力が発生します。削除するには、DCの出力をパイプ処理して、tr -dc 0-9数字以外の文字を削除します。そして、私たちはそこにいます。


スペース処理できるdc -e${#2}o$1p|tr 0-9 "$2"ように、\ escaped形式ではなく文字どおり入力を取得することをお勧めしますが、たとえば、範囲文字として扱わないオプションはありません。入力が文字列の一方の端にない場合、ブレークします。おそらく使用できます。いいえ、GNU では両方の引数の長さを同じにする必要がありますが、改行で詰まるようです。tr--sed "y/0123456789/$2/"sedy
ピーター

2

APL(Dyalog Unicode)14 13 12バイト

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

オンラインでお試しください!

中置暗黙関数; 浮動小数点表現のため、最大のテストケースを処理できません。

保存された1 2は、@アダムのおかげでバイト!

ヘッダーに追加さ13バイト:⎕IO←0I NDEX O RIGIN = 0 ⎕FR←1287Fのフロートの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

スタックス、2バイト

:B

実行してデバッグする

:Bこれを行うstaxの命令です。通常、「文字列」の配列ではなく、「文字列」*で動作します。結局、これは、出力が単一文字配列の配列であることを意味します。ただし、出力は暗黙的にフラット化されます。

* 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バイトをバッファの先頭にコピーする場合は、最後に1つ実行できます。
ピーター

それは素晴らしいです。扱いにくいI / O形式かどうかは気にしません。厄介なI / OはCの名声です!よくできました。これをCのヒントポストに追加することをお勧めします。
ラムダベータ

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 is Flexible"なのでliq、最初はこれを取り除くことができ、3バイト節約できます!
クロム

1

JavaScript、39バイト

Port of RodのPythonソリューション

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

オンラインで試す


n最大64ビットでのみ動作しますか?(Pythonには任意精度の整数が組み込まれていますが、JS番号は自然にdouble-整数に変換できる精度の浮動小数点数です)。1928149325670647244912100789213626616560861130859431492905908574660758972167966のように、質問内のより大きなテストケースでは機能しないようです。それでも、注意する必要があります。
ピーター・コーデス

1

SimpleTemplate、86バイト

うわー、これは大きな挑戦でした!

これは、インデックスが変数であるときに特定のインデックスに直接アクセスできないために困難になりました。
また、バグにより変数が長くなり、値を変数内に保存する必要がありました。

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

期待される値:

最初の引数(argv.0)は次のとおりです。

  • 整数
  • 数字を含む文字列
  • 整数の配列

2番目の引数(argv.1)は次のとおりです。

  • 文字列
  • 配列

これはどのように機能しますか?

次のように機能します。

  • 最初の引数として渡された数値/文字列を循環します
  • 変数Cを含む配列に変数を設定します:
    • 前の値 C
    • 文字列 "{@echoA."
    • ループの値
    • 文字列 "}"
  • (PHPの使用して、すべての合流join機能)を
    、例えば、ではこの結果をC含みます"{@echoA.0}{@echoA.1}..."
  • の結果を評価します C

ゴルフをしていない:

{@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.