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 그것을 떠나 skewstd있지만 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)), 어디 nb왼쪽과 오른쪽 인수는

D 특정 물건

슬프게도, 우리는 수입에 필요 std.conv이상으로 모든 종류의 변환을 수행하는 매우 기본적인 형식 변환.

(그것을 호출하면 그냥 이유입니다되는 golfy 템플릿 시스템을 사용하고 기능을 필요한 유형을 제공 u(n,b)), 우리는의 발생이 단축 될 수 있습니다 char[]ulong1, 각 바이트를 할 때 함수 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 -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 형식 대신 문자 그대로 입력 하는 것이 좋습니다 . 그러나 예를 들어 범위 문자로 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.