base-n 숫자의 ASCII 아트 압축 해제


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포함합니다. 즉, 가장 작은 밑은 이진수이고 가장 큰 밑은 십진수입니다 ( 여기서는 성가신 글자 는 없습니다 )
  • 표준 허점 은 금지되어 있습니다
  • 귀하의 언어가 더 큰 테스트 사례를 처리 할 수없는 경우에도 대답하십시오.

이것이 이므로 각 언어에 대한 가장 짧은 코드가 승리합니다. ( 나는 당신이 모든 골프 언어에 갈 준비가 1 바이트 내장되어 있다는 것을 알고 있습니다 .)


샌드 박스 (삭제됨)
— Jo King

3
D' awwh, 영광입니다. 05AB1E ascii-art 는 내가 좋아하는 시간이었습니다.
— Magic Octopus Urn

당신은 새로운 도전을 만들 수 있습니다 : 배열에서 문자의 순열을 찾아 숫자를 최소화하십시오 :)
— mazzy

답변:


8

05AB1E , 7 6 바이트

gв¹sèJ

05AB1E 답변에서 영감을 얻었으므로 05AB1E에 주어진 답변이 적합합니다. :)

foreach를 제거하고 암시 적으로 수행함으로써 @Enigma 덕분에 -1 바이트 .

온라인으로 시도 하거나 모든 테스트 사례를 확인하십시오 .

설명:

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이 경우에 동일한 출력을 줄 것입니다.)
— 케빈 Cruijssen

6

자바 8, 72 50 바이트

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

@ OlivierGrégoire 덕분에 -22 바이트 덕분에 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 바이트) 재귀.
— Olivier Grégoire

6

파이썬 3 , 49 바이트

아직 언급 할 수 없으므로 Python 3.5에 적합한 Python 2 답변을 게시합니다.

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

2
PPCG에 오신 것을 환영합니다! 솔루션을 소개하는 데 도움이 되는 TIO 링크 를 자유롭게 포함 하십시오.
— 조 왕

5

apt, 2 바이트

두 번째 입력을 배열 또는 문자열로 취할 수 있습니다. 숫자가 JavaScript의 최대 정수를 초과하므로 마지막 2 개의 테스트 사례가 실패합니다. 교체 s와 ì문자의 배열 대신에 출력한다.

sV

시도 해봐


5

하스켈 , 40 39 바이트

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

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

Haskell의 Int유형이로 제한되어 있으므로 9223372036854775807더 큰 숫자에서는 실패합니다.

Laikoni 덕분에 -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대신 사용하는 것이 좋습니다 mod! div n(length l)바이트를 저장합니다.
— Laikoni 2016 년


4

자바 스크립트 (ES6), 48 바이트

커링 구문에서 입력을 받습니다. (c)(n)여기서 c 는 문자 목록이고 n 은 정수입니다.

n <2 53 에만 안전합니다 .

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

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


JavaScript (ES6), 99 바이트

큰 정수 지원

currying syntax에서 입력을받습니다 (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 바이트

(또한 DF = 1 호출 규칙이있는 32 비트 또는 64 비트 용 16 바이트를 포함하여 아래의 다른 버전도 참조하십시오.)

발신자는 포인터를 포함한 레지스터 인수, 통과 최종 출력 버퍼의 (같은 내 C의 대답을 , 칭의와 알고리즘의 설명을 참조하십시오.) 의 glibc의 내부 _itoa이 작업을 수행 그것은 단지 코드 골프를 위해 고안하지 그래서. arg-passing 레지스터는 EDX 대신 EAX에 arg가 있다는 점을 제외하고 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 호출자는 추가 작업 비용이 들지 않는 사용자 정의 arg-passing 및 return-value 레지스터와 달리) 64 비트 코드에서 cld/ 는 출력 포인터를 32 비트로 자르지 않도록 scasb로 작동합니다. inc rdi64 비트 클린 기능에서 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 또는 17Bstosb_edx_arg
  • 64 비트 포인터가있는 x86-64 및 시작 / 종료 호출 규칙에서 DF = 0 : 17 + 1 바이트 ( stosb_decode_overlap) , 18B ( stosb_edx_arg또는 skew)
  • 64 비트 포인터가있는 x86-64, 기타 DF 처리 : 16B (DF = 1 skew) , 17B ( nostringDF = 1, scasb대신을 사용하여 dec). 18B ( stosb_edx_argDF = 1을 3 바이트로 유지 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 그것을 떠나 skew와 std있지만 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의 나머지를 가져오고 나가는 xchg를 사용합니다 .

시작 / 종료 규칙에 일반적인 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 바이트를 계산합니다.

여기서 멋진 트릭 은 동일한 바이트가 두 가지 다른 방식으로 디코딩되는 것 입니다. 우리는 나머지 = base 및 quotient = 입력 번호로 루프 중간에 들어가고 0 종결자를 제자리에 복사합니다.

함수를 통해 처음으로 루프의 처음 3 바이트는 LEA에 대한 disp32의 상위 바이트로 사용됩니다. LEA는베이스 (모듈러스)를 EDX에 복사하고 idiv나중의 반복을 위해 나머지를 생성합니다.

의 2 바이트 idiv ebpIS FD대한 오피 코드이며, std일 기능이 요구하는 명령. (이 행운의 발견은 내가 함께이보고되었다.이었다 div에서 자신을 구별하는, 이전 idiv은 Using /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. 4 바이트를 효과적으로 앞당기려면 1 바이트 만 소요되며 클로버 링 플래그 만 있습니다. (BTW L1i 캐시에서 명령 경계를 표시하는 CPU의 성능에는 끔찍합니다.)

그러나 여기서는 3 바이트를 사용하여 레지스터를 복사하고 루프로 점프합니다. 보통 2 + 2 (mov + jmp)가 걸리며 XLATB가 아닌 STOS 바로 앞의 루프로 넘어갑니다. 그러나 우리는 별도의 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 바이트에서 덤핑하고 때문에 고정 길이 출력 버퍼. 우리는 함수가 그것으로 생각하고 있었다 바이트를 쓴 것을 볼 수 있도록 하지 않았다 어떤이가하지 말았어야 바이트에 단계.를 함수에 전달 된 시작 포인터는 마지막 두 번째 x문자이며 그 뒤에 0이옵니다.)


3

젤리 , 4 바이트

ṙ1ṃ@

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

ṃ말 그대로 이것에 내장되어 있습니다. 다른 3 바이트는 Jelly의 1 기반 색인 작성을 설명합니다.


호기심 때문에 젤리는 왜 ṃ" 기본 압축 해제; x를 기본 길이 (y)로 변환 한 다음 y로 색인화 "합니까? 변환하려는 기본과 문자열 / 정수 / 목록의 길이가 동일한 매우 예외적 인 경우입니까? 검색 할 때 다음을 사용하여 세 가지 답변 만 찾을 수 있습니다. 1 ; 2 ; 3 . 매일 코드 골프에 이상한 내장 기능이 있습니다. : S
— Kevin Cruijssen 2016 년

3
@KevinCruijssen 예를 들어 숫자 목록 대신 16 진수 문자를 사용하여 N 을 16 진수 로 변환하려는 경우 매우 유용 합니다.
— Mr. Xcoder

@KevinCruijssen 문자열을 압축하는 방법입니다. 첫 번째 예에서 원하는 문자열은입니다 “sspspdspdspfdspfdsp”. 그러나 “çƥ÷£ḟ’ṃ“spdf”¤6 바이트를 절약 할 수 있습니다. Jelly의 기본 250 숫자에 특히 유용합니다
— dylnan


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 바이트입니다 : P (현재 고장 났으므로 인수로 숫자 및 문자열 배열을 사용하지 않습니다) (또한 유용한 암시 적 입력이 어떻게 (나) 유용한 지 궁금합니다)
— ASCII 전용

@ ASCII-only "1 바이트"를 의미하지 마십시오 (-vl 출력;-참조). 또한 암시적인 입력은 이와 같은 문제를 제외하고는 숯에서 거의 쓸모없는 것으로 보입니다.
— Neil

1
단일 "바이트"대신 @ASCII 전용 복수 "바이트"는 Neil의 의미입니다. ;) 귀하의 1 바이트 답변에 대해서는 왜 밖으로 나갔 θη습니까? 약간 혼란스러운 tbh가 보입니다. 왜 완전히 제거하고 떠나지 ⍘않습니까?
— 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;}

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

이것은 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!C정수 n%l를 문자 배열 로 변환하고 (코드 포인트 사용) ~연결

foreach(ref c;t)C ++의 for(... : ...)루프와 비슷하지만 조금 더 길다. ref처럼 &, 그것은 c참조에 의해 복사 된 것으로 취급합니다 (즉, 우리는 수정할 수 있습니다 t). 다행히, D의를 추론의 유형 c없이 어떤 키워드를 의미하는데 유형입니다.



3

C ++, 150 144 바이트 uint64입력

Zacharý 덕분에 -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, "|_")

먼저 숫자, 두 번째는 문자열입니다 (char array)

테스트 사례 :

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;
— Zacharý

@ceilingcat, b.size()루프에서 변경되지 않는 것을 잊었습니다 .
— Zacharý

@ceilingcat 바이트 수를 줄이지 않고 1 씩 늘릴 것입니다.
— HatsuPointerKun

2

나뭇 가지, 66 바이트

템플릿에 포함 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()

언 골프 (비 기능) :

{% 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 덕분에 바이트를 절약하고 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.
— Mr. Xcoder 2016 년

2

C89, 제한된 범위의 서명 int n, 64 53 바이트

  • changelog : a char **out를 가져 와서 반환하는 대신 a를 가져 와서 수정하십시오.char *

숫자를 int, 조회 테이블을 배열 + 길이로 사용합니다.
출력은에 기록됩니다 char *outbuf. 호출자는 버퍼의 끝에 포인터를 참조로 전달합니다. 함수는 반환시 문자열의 첫 번째 바이트를 가리 키도록 해당 포인터를 수정합니다.

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

이것은 유효한 C89이며 최적화가 활성화 된 경우에도 올바르게 작동합니다. 즉 -O0, 비 공백 기능의 끝에서 떨어지거나 다른 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;
}

이 명시 적 길이 버전에서 입력은 문자열로 취급 char table[]되지 않으므로 종료 0 바이트가 필요 하지 않은 입니다. int table[]우리가 걱정하는 모든 것이 될 수 있습니다 . C에는 자체 길이를 알고있는 컨테이너가 없으므로 크기가있는 배열을 전달하는 일반적인 방법은 포인터 + 길이입니다. 그래서 우리는 그 대신에 그것을 선택합니다 strlen.

최대 버퍼 크기는 대략 sizeof(int)*CHAR_BIT + 1이므로 컴파일 타임이 작고 상수입니다. (이 기준은 base = 2이고 모든 비트는 1로 설정됩니다.) 예를 들어 0종료 자를 포함하여 32 비트 정수의 경우 33 바이트입니다 .


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

배쉬 + 코어 유틸리티 , 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 -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는 성가신 "기능"을 가지고 있으며, 많은 수를 출력하는 경우 슬래시 + 줄 바꿈 순서로 줄 바꿈하므로 더 큰 테스트 사례에는이 추가 출력이 있습니다. 그것을 제거하기 위해 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 2016 년

2

APL (Dyalog Unicode) , 14 13 12 바이트

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

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

암묵적 기능을 삽입; 부동 소수점 표현으로 인해 가장 큰 테스트 사례를 처리 할 수 ​​없습니다.

저장 1 2 아담 @ 덕분에 바이트!

헤더 추가 13 바이트 : ⎕IO←0: I 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

캔버스 , 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

Stax , 6 5 바이트

n%|E@

실행 및 디버깅

설명:

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

1

SOGL V0.12 , 10 바이트

l;A─{IaWp}

여기 사용해보십시오!

아이디어가 언어로 거의 구현되었다는 것을 고려하면 꽤 길다. here , enter

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

이 방법을 사용하여 압축 문자열을 제공합니다.



1

Stax , 2 바이트

:B

실행 및 디버깅

:B이 작업을 수행하는 stax의 명령어입니다. 일반적으로 "문자열"배열 대신 "문자열"*에서 작동합니다. 결국 이것은 출력이 단일 문자 배열의 배열임을 의미합니다. 그러나 어쨌든 출력은 암시 적으로 평탄화됩니다.

* 세금에는 실제로 문자열 유형이 없습니다. 텍스트는 코드 포인트의 정수 배열로 표시됩니다.


허, 나는이 명령을 보지 못했다 ...
— wastl

많이 있습니다. 나는 이미 존재했던 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 2016 년

훌륭합니다. 어색한 I / O 형식인지는 상관하지 않습니다. 어색한 I / O는 C의 명성입니다! 잘 했으므로 C 팁 게시물에 넣는 것이 좋습니다.
— LambdaBeta

기술을 설명하고 정당화하는 C의 골프 팁에 대한 답변을 게시했습니다 .
— Peter Cordes

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

자바 스크립트, 39 바이트

Port of Rod의 Python 솔루션 .

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

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


n최대 64 비트 에서만 작동 합니까? (Python에는 임의의 정밀도 정수가 내장되어 있지만 JS 숫자는 자연스럽게 double정수로 변환 할 수있는 정밀 부동 소수점입니다). 1928149325670647244912100789213626616560861130859431492905908574660758972167966과 같은 질문에서 더 큰 테스트 사례에는 작동하지 않는 것 같습니다. 그러나 질문에 대한 답변은 가능합니다. 여전히 주목해야합니다.
— Peter Cordes

1

SimpleTemplate , 86 바이트

와우, 이것은 큰 도전이었다!

인덱스가 변수 일 때 특정 인덱스에 직접 액세스 할 수 없기 때문에 이것은 어려워졌습니다.
또한 버그로 인해 변수 내부에 값을 저장해야했습니다.

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

예상되는 값 :

첫 번째 인수 ( argv.0)는 다음과 같습니다.

  • 정수
  • 숫자가있는 문자열
  • 정수 배열

두 번째 인수 ( argv.1)는 다음과 같습니다.

  • 끈
  • 배열

어떻게 작동합니까?

이 방법으로 작동합니다 :

  • 첫 번째 인수로 전달 된 숫자 / 문자열을 순환합니다.
  • 변수 C가 다음을 포함하는 배열이되도록 설정합니다 .
    • 이전 값 C
    • 끈 "{@echoA."
    • 루프의 가치
    • 끈 "}"
  • 모든 join기능을 결합합니다 (PHP 기능 사용).
    예를 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.