Bir n sayısından ASCII sanatı sıkıştırması


24

Bu esinlenerek 05AB1E cevap tarafından Sihirli Octupus Urn .

İki argüman, pozitif bir tamsayı ve bir karakter / karakter listesi verildi:

  1. Sayıyı base-n'ye çevirin, burada n dize uzunluğudur.
  2. Her karakter için, bu karakterin dizinindeki her görünümü, temel n sayısındaki karakterle değiştirin.
  3. Yeni dizeyi yazdırın veya iade edin.

Örnekler:

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

Kurallar:

  • IO esnektir .
    • Girdiler arasında tutarlı olduğu sürece herhangi bir temeldeki numarayı alabilirsiniz.
    • Karakter listesi 0 dizinli olmalı, burada 0 ilk karakter ve n-1 son karakter
  • Muhtemel karakterler, basılabilir ASCII, sekmeler ve yeni satırlar gibi boşluklarla birlikte olabilir
  • Verilen karakter listesinin 2-10dahil olduğu aralıkta bir uzunluğu olacaktır . Yani, en küçük taban ikiliktir ve en büyük ondalıktır ( burada sinir bozucu harfler yoktur ).
  • Standart boşluklar yasaktır
  • Diliniz daha büyük sınav durumlarıyla başa çıkmasa bile cevap vermekten çekinmeyin.

Bu , her dil için en kısa kod kazanır. ( Tüm golf dillerinde kullanmaya hazır bir bayt yerleşik olduğunu biliyorum ;)


Sandbox (silindi)
Jo King

3
D'awwh, onur duyuyorum. 05AB1E ascii-art , bir süredir en sevdiğim zamandı .
Magic Octopus Urn

yeni bir meydan okuma oluşturabilirsiniz: dizi en aza indirmek için dizideki karakterlerin permütasyonunu bulabilirsiniz :)
mazzy

Yanıtlar:


8

05AB1E , 7 6 bayt

gв¹sèJ

05AB1E'nin bir cevabından ilham aldığından 05AB1E'de verilen bir cevap uygun görünüyor. :)

-Enigma sayesinde foreazı çıkartarak ve bunu yaparak.

Çevrimiçi deneyin veya tüm test durumlarını doğrulayın .

Açıklama:

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èJBir bayt kaydetmek için
Emigna

@Emigna Teşekkürler. Ben düşünmemiştim inanamıyorum ¹sèşimdi kendim .. (değişiyorum bilen ?bir karşı Jbu durumda aynı çıktıyı verecek.)
Kevin Cruijssen

6

Java 8, 72 50 bayt

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

-22 byte @ OlivierGrégoire sayesinde IntStreamdoğrudan baskı yapmak yerine iade ederek .

Çevrimiçi deneyin .

Açıklama:

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 bayt) "IO esnek" olduğundan beri
Olivier Grégoire

String f(char[]a,int n){return n>0?f(a,n/a.length)+a[n%a.length]:"";}(69 bayt) özyinelemeli, eğlence için.
Olivier Grégoire

6

Python 3 , 49 bayt

Henüz yorum yapamıyorum, bu yüzden Python 3.5'e uyarlanmış Python 2 cevabını gönderdim.

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

2
PPCG'ye Hoşgeldiniz! Çözümünüzü sergilemek için bir TIO bağlantısı eklemekten çekinmeyin .
Jo King,

5

Japt, 2 bayt

İkinci girişi bir dizi veya dize olarak alabilir. Sayılar JavaScript'in maksimum tamsayısını aştığı için son 2 test senaryosunda başarısız olur. Bunun yerine bir karakter dizisi çıkarmak için sile değiştirin ì.

sV

Dene


5

Haskell , 40 39 bayt

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

Çevrimiçi deneyin!

Haskell'in Inttipi sınırlı olduğu için 9223372036854775807, bu daha büyük sayılar için başarısız olur.

Laikoni sayesinde -1 bayt .

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)

Çevrimiçi deneyin!


Kullanımına Güzel fikir cycleyerine mod! div n(length l)bir bayt kaydeder.
Laikoni

4

MATL , 2 bayt

YA

Çevrimiçi deneyin!

Girişler bir sayı ve bir dizedir.

2^53Kayan nokta hassasiyetinden dolayı sayıların aşılması başarısız .

açıklama

Ne YAbilirsiniz, bir yerleşik (belirtilen hedef sembollerle temel dönüştürme).


4

JavaScript (ES6), 48 bayt

Sözdizimini tımar olarak girişi alır (c)(n)burada, c karakterlerin bir listesini ve n, bir tam sayı olduğu.

Sadece n <2 53 için güvenli .

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

Çevrimiçi deneyin!


JavaScript (ES6), 99 bayt

Büyük tamsayılar desteği ile

Kuran sözdiziminde girdi alır (c)(a); c , bir karakter listesidir ve a , ondalık basamakların bir listesidir (tamsayılar olarak).

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

Çevrimiçi deneyin!


4

x86 32 bit makine kodu (32 bit tam sayılar): 17 bayt.

(ayrıca, 32 bit veya 64 bit için 16 bayt, DF = 1 arama kuralı dahil olmak üzere, aşağıdaki diğer sürümlere bakın.)

Arayan bir işareti içeren kayıtları args, geçer sonuna bir çıkış tamponunun (gibi benim C cevap ; gerekçe ve algoritmanın açıklaması için görüyorum.) Glibc iç _itoayapar sadece kod golf için yapmacık değil yani. Argüman geçiren kayıtlar, EDX yerine EAX'te bir argümanımız olması dışında, x86-64 System V'ye yakındır.

Dönüşte, EDI çıkış arabelleğindeki 0-sonlandırılmış bir C dizesinin ilk baytına işaret eder. Her zamanki getiri-değer yazıcısı EAX / RAX'dır, fakat assembly dilinde bir işlev için uygun olan arama kuralını kullanabilirsiniz. ( xchg eax,edisonunda 1 bayt ekler).

Arayan, isterse açık bir uzunluk hesaplayabilir buffer_end - edi. Ancak, işlev aslında hem başlangıç ​​+ bitiş işaretçilerini hem de işaretçi + uzunluğu döndürmedikçe sonlandırıcıyı atlamayı haklı çıkartabileceğimizi sanmıyorum. Bu sürümde 3 byte tasarruf sağlar, ancak haklı olduğunu sanmıyorum.

  • EAX = n = kod çözülecek sayı. (Çünkü idiv. Diğer argümanlar gizli operandlar değildir.)
  • EDI = çıkış arabelleğinin sonu (64 bit sürüm hala kullanılıyor dec edi, bu nedenle düşük 4GiB'de olmalı)
  • ESI / RSI = arama tablosu, aka LUT. gizlenmemiş.
  • ECX = tablonun uzunluğu = taban. gizlenmemiş.

nasm -felf32 ascii-compress-base.asm -l /dev/stdout | cut -b -30,$((30+10))- (Elleri yorumlamak için düzenlendi, satır numaralandırma tuhaf.)

   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

Temelde hız / boyut geçişi olmayan en basit sürümün, en aza inen , ancak azalan düzende kullanmak ve hala ortak DF = 0 arama kuralını takip etmek için kullanılan std/ cldmaliyetin 2 bayt olması şaşırtıcıdır stosb. (STOS sakladıktan sonra azalır , işaretçiyi loop çıkışında bir bayt işaretini çok düşük bırakır ve etrafta çalışmamız için ekstra bayt tutar.)

sürümleri:

4 farklı uygulama hilesi kullandım (basit movyük / depo kullanarak (yukarıda), lea/ kullanarak movsb(düzgün ama optimal değil), xchg/ xlatb/ stosb/ kullanarak xchgve üst üste binen bir talimat kesmesiyle döngüye giren bir tane kullandım). . Sonuncusu 0, çıkış dizgisi sonlandırıcısı olarak kopyalamak için arama tablosundaki bir sonuca ihtiyaç duyuyor , bu yüzden bunu +1 bayt olarak sayıyorum. 32/64-bit (1 bayt incveya değil) ve arayanın DF = 1 ( stosbazalan) veya her neyse, farklı versiyonların (bağlı olduğu) en kısa sürdüğünü varsayamayacağımıza bağlı olarak.

Azalan düzende saklamak için DF = 1, onu xchg / stosb / xchg'ye kazanır, ancak arayan çoğu zaman bunu istemez; Arayana gerekçelendirilmesi zor bir şekilde boşaltma çalışması gibi geliyor. Ama 64 bit kodunda, (tipik fazladan bir çaba. Arayan bir asm maliyeti olmayan özel arg-geçiyordu ve dönüş-değeri kayıtlarını aksine) cld/ scasbolarak çalışır inc rdibazen bu yüzden, 32-bit çıkış işaretçisi kesiliyor kaçınarak, 64 bit temizleme işlevlerinde DF = 1 değerini korumak sakıncalıdır. . (Statik kod / verilere yönelik işaretçiler, Linux'ta x86-64'te PIE olmayan çalıştırılabilir dosyalarda 32 bit, ve her zaman Linux x32 ABI'de, bu nedenle 32 bit işaretleyicileri kullanan bir x86-64 sürümü bazı durumlarda kullanılabilir.) Bu etkileşim farklı gereksinimlerin kombinasyonlarına bakmayı ilginçleştirir.

  • Giriş / çıkış arama kuralında DF = 0 olan IA32: 17B ( nostring) .
  • IA32: 16B (bir DF = 1 kuralına göre: stosb_edx_argveya skew) ; veya gelen DF = umurumda değil, ayarlanmış halde bırakarak: 16 + 1Bstosb_decode_overlap veya 17Bstosb_edx_arg
  • 64 bit işaretçilerle x86-64 ve giriş / çıkış arama konvansiyonunda bir DF = 0: 17 + 1 bayt ( stosb_decode_overlap) , 18B ( stosb_edx_argveya skew)
  • 64 bit işaretçilerle x86-64, diğer DF işlemleriyle: 16B (DF = 1 skew) , 17B ( nostringyerine DF = 1 scasbile dec). 18B ( stosb_edx_argDF = 1'i 3 bayt ile koruyarak inc rdi).

    Veya dizeden önce göstergenin 1 bayta dönmesine izin verirsek, 15B ( stosb_edx_argolmadan incsonunda). Hepsi tekrar arayacak ve başka bir dizgeyi farklı bir taban / tabloya sahip arabellek içine genişletecek şekilde ayarlanmış ... Ama eğer bir sonlandırıcı depolamazsak 0, işlev gövdesini bir döngünün içine koyabilirsin, bu gerçekten bir Ayrı sorun.

  • 32 bit çıkış işaretçisiyle x86-64, DF = 0 arama kuralı: 64 bit çıkış işaretçisinde daha fazla gelişme olmaz, ancak 18B ( nostring) şimdi bağlanır.

  • 32 bit çıkış işaretçisiyle x86-64: en iyi 64 bit işaretçi sürümlerinde hiçbir iyileştirme yok, bu nedenle 16B (DF = 1 skew). Veya DF = 1 set ve için, 17B bırakmak skewile stddeğil cld. Veya 17 + 1B içinstosb_decode_overlap birlikte inc ediyerine sonundaki cld/ ' scasb.

DF = 1 arama kuralı ile: 16 bayt (IA32 veya x86-64)

Girişte DF = 1 gerekir, ayarlanmış halde bırakılır. En azından işlevsellik temelinde zar zor mantıklı . Yukarıdaki sürümle aynı şeyi yapar, ancak XLATB'den önce / sonra geri kalanı almak / almak için xchg ile xchg (temel olarak R / EBX ile tablo araması) ve STOSB ( *output-- = al).

Giriş / çıkış kurallarında normal bir DF = 0 olduğunda , std/ cld/ scasbsürümü 32 ve 64 bit kod için 18 bayttır ve 64 bit temizdir (64 bit çıkış işaretçisiyle çalışır).

Giriş argümanlarının tablo için RBX de dahil olmak üzere farklı kayıtlarda olduğunu unutmayın (for xlatb). Ayrıca, bu döngünün AL'yi depolayarak başladığını ve henüz kaydedilmemiş son karakterle sona erdiğini unutmayın (bu nedenle movsonunda). Bu yüzden döngü diğerlerine göre "çarpıktır", dolayısıyla adı.

                            ;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

Benzer olmayan bir eğri olmayan sürüm EDI / RDI'yı aşıyor ve daha sonra düzeltiyor.

                            ; 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

Bunun alternatif bir versiyonunu denedim lea esi, [rbx+rdx]movsb iç döngü gövdesi olarak / . (RSI her yinelemeyi sıfırlar, ancak RDI azalır). Ancak sonlandırıcı için xor-zero / stos kullanamaz, bu yüzden 1 bayt daha büyüktür. (Ve LEA'da bir REX öneki olmadan arama tablosu için 64-bit temiz değil.)


Açık uzunlukta LUT ve 0 terminatör : 16 + 1 bayt (32-bit)

Bu sürüm DF = 1 ayarını yapar ve bu şekilde bırakır. Toplam bayt sayımının bir parçası olarak gereken ekstra LUT baytını sayıyorum.

Buradaki harika numara , aynı baytların iki farklı yolla kodunu çözmesidir. . Kalan dönemin ortasına remainder = base ve quotient = input numarası ile düşersek 0 terminatörünü yerine kopyalarız.

İşlev boyunca ilk defa, döngünün ilk 3 baytı bir LEA için bir disp32'nin yüksek baytı olarak tüketilir. LEA, tabanı (modülü) EDX'e kopyalar, idivkalanları daha sonraki yinelemeler için üretir.

2. bayt idiv ebpDİR FDiçin işlem kodu, stdişe bu fonksiyon ihtiyaçları olduğunu talimat. (Bu şanslı bir keşif ben bu bakarak edilmişti. İdi divile ayrılıyor, hangi önceki idivkullanarak /r. ModRM içinde bitleri 2. bayt div epbolarak deşifre cmcyararlı zararsız ama değil. Ama birlikte idiv ebpbiz aslında kaldırabilirsiniz stdüstten Fonksiyonun

Giriş kayıtlarının bir kez daha farklılık gösterdiğini unutmayın: Temel için 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

Bu çakışan kod çözme numarası ayrıca ... cmp eax, imm32 : 4 bayt, yalnızca gizleme bayraklarını etkin şekilde atlamak yalnızca 1 bayt alır. (Bu, BT1'deki L1i önbelleğindeki komut sınırlarını işaretleyen CPU'lardaki performans için korkunçtur.)

Ancak burada, bir kayıt defterini kopyalamak ve döngüye atlamak için 3 bayt kullanıyoruz. Bu normalde 2 + 2 (mov + jmp) alacaktır ve XLATB'den önce STOS'tan hemen önce döngüye atlamamıza izin verecektir. Ama sonra ayrı bir STD'ye ihtiyacımız olacaktı ve çok ilginç olmazdı.

Çevrimiçi deneyin! ( _startsonuçta kullanan bir arayan ile sys_write)

Bu hata ayıklama için altında çalıştırmak straceveya çıktının hexdump yapmak için en iyisidir , böylece \0doğru yerde bir terminatör olduğunu doğrulayabilirsiniz . Fakat bunun gerçekten işe yaradığını ve bunun AAAAAACHOOiçin bir girdi ürettiğini görebilirsiniz .

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

(Aslında xxAAAAAACHOO\0x\0\0...biz daha önce de 2 byte dan damping çünkü sabit bir uzunluğa dışarı tampon. Biz işlevi gerekiyordu ve oldu bayt yazdığını görebilirsiniz Yani vermedi herhangi bunu olmamalıdır bayt Gazla. işleve geçen start-pointer x, onu takip eden sıfır olan 2. son karakterdi.


3

Jöle , 4 bayt

ṙ1ṃ@

Çevrimiçi deneyin!

kelimenin tam anlamıyla bunun için bir yerleşiktir. Diğer üç bayt Jelly'in tek tabanlı endekslemesini oluşturur.


Meraktan dolayı, Jelly neden " Temel dekompresyon; x'i taban uzunluğuna (y) dönüştürün, sonra indeksi y'ye dönüştürün " ifadesine neden sahip değil ? Dönüştürmek istediğiniz tabanın ve bir dizgenin / tamsayı / listenin uzunluğunun eşit olduğu istisnai durumlar için mi? Aradığımda, onu kullanarak sadece üç cevap bulabilirim: 1 ; 2 ; 3 . Her gün kod-golf mücadelelerinde çok garip bir yerleşik imo. : S
Kevin Cruijssen

3
@KevinCruijssen, örneğin bir sayı listesi yerine onaltılık harfler kullanarak N'yi onaltılık alana dönüştürmek istediğinizde çok kullanışlıdır .
Bay Xcoder

@KevinCruijssen Bu dizeler için bir sıkıştırma yöntemidir. İlk örnekte istenen dize “sspspdspdspfdspfdsp”, ancak “çƥ÷£ḟ’ṃ“spdf”¤sizinle altı bayt kaydedin.
Jelly'in


3

Kömür , 3 1 bayt

θη

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı bir versiyonudur. Düzenleme: Yalnızca @ ASCII-sayesinde 2 bayt kaydedildi. Yerleşik eklenmeden önceki sürüm, 8 bayt:

⭆↨θLη§ηι

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı bir versiyonudur. Açıklama:

    η       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

Aslında zaten çalışması gerekiyordu ama açıkçası yine de berbat ettim
ASCII-

Ayrıca, aslında 1 byte olur : P (şu anda bozuldu, bu yüzden sayı ve string dizisini argümanlar olarak kullanmıyorum) (ayrıca merak ediyorum (un) yararlı örtülü girdilerin ne olduğunu merak ediyorum)
ASCII-sadece

@ ASCII-Yalnızca "1 bayt" demek istemiyorsunuz (-vl çıktınıza bakınız ;-) Ayrıca, örtük girdi, bunun gibi zorluklar dışında, Kömür'de neredeyse işe yaramaz gibi görünmektedir.
Neil

1
@ ASCII-sadece Tekil "byte" yerine çoğul "bayt" Neil'in ne anlama geldiğidir. ;) 1 baytlık cevabınız gelince, neden çarpı işareti θη? Kafa karıştırıcı biraz tbh görünüyor. Neden sadece tamamen çıkartıp bırakmıyorsunuz ?
Kevin Cruijssen

1
@Nit kontrol ettim ve soru sorulmadan önce dahili olarak eklenmiş olmuştu, ancak bir hata olduğu için fark etmemiştim.
Neil

3

D , 112 bayt

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

Çevrimiçi deneyin!

Bu HatsuPointerKun'un C ++ cevabının limanı.

Çağıran stil, sol ve sağ argümanlar u(ulong(n), to!(char[])(b))nerede nveb

D belirli şeyler

Ne yazık ki, çok temel tür dönüşümünün std.convüzerindeki herhangi bir tür dönüşümünü yapmak için içe aktarmamız gerekiyor .

Golfy şablon şablonunu kullanarak ve işleve gerekli tipleri vererek (bu nedenle sadece çağırmanın nedeni bu değiliz u(n,b)), işlevin içindeyken her birinin oluşumunu char[]ve bayt ulongsayısını kısaltabiliriz 1.

D yüzden bizim için bizim türlerini başlatır C t;kısaltmasıdırC t=cast(char[])([])

to!Ctamsayıyı n%lbir karakter dizisine dönüştürür (kod noktaları kullanarak) ve ~bitiştirme

foreach(ref c;t)C ++ 'ın for(... : ...)döngüsü gibi, ama biraz daha uzun. refgibidir &, creferansa göre kopyalanmış gibi davranır (yani değiştirebiliriz t). Neyse ki, D herhangi bir anahtar kelime ifade türü colmadan türünü etkilemektedir .



3

C ++, 150 144 bayt, uint64giriş

Zacharý sayesinde -6 bayt

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

Boyutu depolamak için bir değişken kullanmak, bytecount değerini 1 artırabilir.

Fonksiyonu çağırmak için:

u(2740, "|_")

İlk sayı, ikincisi string'tir (char array)

Test durumları:

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

1
Tıraş olmak için 3 bayt: Sonra boşluğa ihtiyacınız yok #include, ;;sadece değişebiliyorsunuz ;ve '0'sadece olabilir48
Zacharı

1
Ayrıca, süre döngüsü bir döngü olabilir for:for(;n;n/=b.size())t=std::to_string(n%b.size())+t;
Zacharý

@ceilingcat, b.size()bu döngüde değişmediğini unuttum .
Zacharı,

@ceilingcat Bu, bytecount değerini düşürmek yerine 1 artıracaktır
HatsuPointerKun

2

Dal, 66 bayt

Bir şablona girilmesi macrogereken bir a düzenlendi import.

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

Beklenen değerler:

İlk argümanlar için ( n):

  • numara
  • sicim

İkinci argüman için ( c):

  • Sayı dizisi
  • Dizeler dizisi

Nasıl kullanılır:

  • Bir .twigdosya oluştur
  • Eklemek {% import 'file.twig' as uncompress %}
  • Makroyu ara uncompress.d()

Ungolfed (işlevsel değil):

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


Bu kodu test edebilirsiniz: https://twigfiddle.com/54a0i9


2

Pyth, 9 8 7 bayt

s@LQjEl

Bay Xcoder'a hakr14 ve bir başka teşekkür sayesinde bir bayt kaydedildi.
Burada dene

açıklama

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.

Değiştirerek byte tasarruf m@Qdile@LQ
hakr14

Değiştirerek byte tasarruf vzile E.
Bay Xcoder,

2

C89, sınırlı aralık imzalı int n, 64 53 bayt

  • changelog: a almak char **outve değiştirmek, yerine almak ve geri dönmekchar *

Sayıyı int, arama tablosunu dizi + uzunluk olarak alır.
Çıktı a char *outbuf. Arayan (referans olarak) arabellek sonuna bir işaretçi geçer. İşlev, döndürülen dizenin ilk baytına işaret etmek için bu işaretçiyi değiştirir.

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

Bu C89 geçerlidir ve optimizasyon etkinken bile düzgün çalışır. yani gcc'ye bağlı değil-O0 boş olmayan bir fonksiyonun sonundan düştüğünde veya başka bir UB'ye sahipken davranışına .

Bir işaretçiyi arabellek sonuna geçirmek, glibc'nin internal_itoa gibi optimize edilmiş bir int string işlevi için normaldir . Burada yaptığımız gibi bir div / mod döngüsüne sahip bir tamsayıyı rakamlara bölmenin ayrıntılı bir açıklaması için bu cevaba bakınız . Baz 2 değerinde bir güç ise, önce MSD rakamlarını çıkarmak için kaydırma / maske yapabilirsiniz, ancak aksi takdirde sadece iyi seçenek ilk önce en az anlamlı olan rakamdır (modulo ile).

Çevrimiçi deneyin! . Ungolfed versiyonu:

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

Bu açık uzunlukta versiyonunda, girdi bir olduğunu char table[]mu hangi değil bir dize olarak muamele çünkü hiçbir zaman, bir sonlandırma 0 bayt gerekir. Tek int table[]umursadığımız bir şey olabilir . C kendi uzunluklarını bilen kaplara sahip değildir, bu nedenle pointer + length, bir boyuta sahip bir dizi iletmenin normal yoludur. Yani buna ihtiyacımız yerine onu seçiyoruz.strlen .

Maksimum tampon boyutu yaklaşıktır sizeof(int)*CHAR_BIT + 1, bu nedenle küçük ve derleme zamanı sabitidir. (Bu kadar boş alanı base = 2 ve 1 olarak ayarlanan tüm bitler ile kullanırız.) Örneğin, 32 bit tamsayılar için 33 bayt, 0sonlandırıcı dahil .


C89, imzalı int, örtük uzunlukta bir C dizesi olarak tablo, 65 bayt

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

Bu aynı şeydir, ancak girdi örtük uzunlukta bir dizedir, bu yüzden uzunluğu kendimiz bulmalıyız.


2

Bash + çekirdek yardımcı programları , 49 bayt

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

Çevrimiçi deneyin!

Yorumlar / açıklama

Bu, komut satırı argümanlarını giriş (10 tabanındaki sayı, ardından karakter listesiyle birlikte tek bir dize) olarak alır ve stdout'a çıkar. Boşluk, yeni satır, vb. Gibi özel karakterler, sekizlik notasyonda (örneğin, \040bir boşluk için) ya da \nyeni bir satır \tiçin, sekme için veya aynı şekilde yorumlayan echo -eve başka herhangi bir kaçış dizisinde girilebilir tr.

Buradaki baytların çoğu, özel karakterleri ve daha büyük test durumlarını ele almak içindir. Yalnızca korkunç olmayan karakterleri kullanmam gerekiyorsa ve sayılar küçükse (örneğin, ilk sınama durumu), aşağıdaki 24 bayt bunu yapacaktır:

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

Bu ${#2}, karakter dizisindeki karakter sayısını elde etmek için parametre genişletmeyi kullanır , baz dönüşümünü yapmak için bir dc programı oluşturur ve sonra dönüştürülen numarayı gönderir.tr .

Ancak bu, yeni satırları veya boşlukları veya sekmeleri ele almaz, bu nedenle, kaideyi etkilemeden kaçış dizileriyle başa çıkmak wc -ciçin kaçışları yorumladıktan sonra bir karakter sayımı yapıyorum echo -en. Bu, programı 38 bayta genişletir:

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

Ne yazık ki, dc, çok sayıda çıktı veriyorsa, bir eğik çizgi + newline dizisi ile saracak, böylelikle daha büyük test durumlarında bu fazladan çıkışa sahip olacak sinir bozucu bir "özelliğe" sahiptir. Çıkarmak için, tr -dc 0-9sayısal olmayan karakterleri silmek için dc çıkışını iletiyorum . Ve işte oradayız.


dc -e${#2}o$1p|tr 0-9 "$2"Girdiyi \ kaçışılmış biçim yerine tam anlamıyla almanızı önereceğim , böylece boşlukları tutabiliyor , ancak örneğin bir aralık karakteri gibi trdavranmama seçeneği yok -. Giriş -dizenin bir ucunda değilse, kopar. Belki kullanabilirsiniz sed "y/0123456789/$2/". Hayır, sanmıyorum, GNU sedher iki argümanın yda aynı uzunlukta olmasını gerektiriyor ve yeni hatta boğuluyor gibi görünüyor.
Peter Cordes,

2

APL (Dyalog Unicode) , 14 13 12 bayt

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

Çevrimiçi deneyin!

Taklit yapışkan işlevi; kayan nokta gösterimi nedeniyle en büyük test durumuyla baş edemiyoruz.

Kaydedilen 1 2 Adam @ sayesinde bayt!

Başlıklar için 13 bayt eklendi ⎕IO←0:: I ndex o rigin = 0 ve ⎕FR←1287: F R enarmasyonu = 128 bit. (Bunun geçerli olmadığını unuttum . )

Nasıl?

⊢⌷⍨∘⊂⊥⍣¯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.

2

Ataşesi , 17 bayt

{_[_2&ToBase!#_]}

Çevrimiçi deneyin!

açıklama

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

1

Tuval , 7 bayt

L┬{╵⁸@p

Burada dene!

Dümdüz ileri uygulama:

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

Girdi karakter seti, yeni bir satır içermediği sürece bir dize olabilir; çünkü Canvas, yeni satır karakterine sahip değildir ve otomatik olarak 2B nesneye dönüştürür.


1

Stax , 6 5 bayt

n%|E@

Koş ve hata ayıkla

Açıklama:

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 bayt

l;A─{IaWp}

Burada dene!

Oldukça uzun, fikrindeydiler hemen hemen dilinde kurulmuştur: burada , girme

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

Bu yöntemi kullanarak sıkıştırılmış bir dize verir.



1

Stax , 2 bayt

:B

Koş ve hata ayıkla

:Bstax'ta bunu yapan bir talimattır. Normalde bir "string" dizisi yerine "string" * ile çalışır. Sonunda, bu, çıkışın tek karakterli dizilerin bir dizisi olduğu anlamına gelir. Fakat çıktı zaten yine de düzleşiyor.

* Stax aslında bir dize türüne sahip değildir. Metin kod noktaları tamsayı dizileriyle gösterilir.


Huh, bu komutu hiç farketmedim ...
wastl

Çok fazla var. Bir keresinde zaten var olan stax'a bir talimat ekledim ve daha önce unutmuştum. (dizi azalan değil?)
özyinelemeyle

1

J , 12 bayt

]{~#@]#.inv[

Nasıl?

      #.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        

Çevrimiçi deneyin!



1

C (gcc) , 110 bayt

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

Çevrimiçi deneyin!

Açıklama:

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
Bir tamponun sonunda başlar ve geriye doğru çalışırsanız, kaçınabilirsiniz sprintf. C versiyonum 53 bayttır , arayan tarafından sağlanan çıkış tamponu ile. strcpyBaytları bir arabellek başlangıcına kopyalamak istiyorsanız, sonunda bir tane yapabilirsiniz .
Peter Cordes

Bu harika. Garip bir G / Ç formatı olması umrumda değil. Garip bir G / Ç C'nin şöhret iddiası! Aferin, bunu C ipucu direğine koymanı tavsiye ederim.
LambdaBeta

Tekniği açıklamak ve haklı çıkarmak için C'deki golf için ipuçları hakkında bir cevap yayınladı .
Peter Cordes

1

CJam , 11 bayt

liq_,@\b\f=

Çevrimiçi deneyin! ASCII resmindeki karakterlerden sonra sayı, sonra bir satır, sonra yeni bir satır girilir.

açıklama

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 Esnek" olduğundan, liqbaşlangıçtan kurtulabileceğinizi düşünüyorum ve bu size 3 bayt kazandırır!
Chromium

1

JavaScript, 39 bayt

Port Rod Python çözüm .

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

Çevrimiçi deneyin


Sadece n64-bit'e kadar çalışır , değil mi? (Python yerleşik olarak isteğe bağlı hassas tam sayılara sahiptir, ancak JS numaraları doğal doubleolarak tam sayıya dönüştürülebilen hassas saydamlardır). 1928149325670647244912100789213626616560861130859431492905908574660758972167966 gibi, sorudaki daha büyük test senaryoları için işe yaramadı. Yine de dikkat edilmelidir.
Peter Cordes

1

SimpleTemplate , 86 bayt

Vay, bu çok büyük bir zorluktu!

Bu, endeks değişken olduğunda belirli endekslere doğrudan erişimin olmaması nedeniyle zorlaştırılmıştır.
Bir hata ayrıca, değerleri değişken içinde saklamayı gerektirerek daha uzun sürdü.

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

Beklenen değerler:

İlk argüman ( argv.0) olabilir:

  • Bir tam sayı
  • Sayı içeren bir dize
  • Bir tam sayı dizisi

İkinci argüman (argv.1 ) olabilir:

  • Dizi
  • Bir dizi

Bu nasıl çalışıyor?

Bu şekilde çalışır:

  • İlk argüman olarak geçirilen sayı / dizgede geçiş yapar
  • Değişkeni ayarlar C içeren bir dizi olacak şekilde :
    • Önceki değer C
    • Dize "{@echoA."
    • Döngünün değeri
    • Dize "}"
  • Her şeyi bir araya getirir (PHP'nin joinişlevini kullanarak )
    Bu, örneğin Ciçeren"{@echoA.0}{@echoA.1}..."
  • Sonucunu değerlendirir C

Ungolfed:

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

Bu kodu deneyebilirsiniz: https://ideone.com/NEKl2q


Optimal sonuç

Eğer böcek olmasaydı, bu sınırlamaları hesaba katarak en iyi sonuç olurdu (77 bayt):

{@eachargv.0}{@setC C,"{@echoargv.1.",_,"}"}{@calljoin intoC"",C}{@/}{@evalC}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.