Espandi una stringa codificata


18

C'è la classica codifica e decodifica della lunghezza della corsa.

input   output
a3b2c5  aaabbccccc

E questo è abbastanza semplice e fatto prima.

La sfida è anche quella di tenere conto di un comportamento non standard quando più caratteri precedono la lunghezza della corsa (una singola cifra compresa tra 0 e 9). A ciascun carattere prima della cifra della lunghezza della corsa (l'ultima cifra prima di una non cifra o la fine della stringa) viene applicato quel valore singolarmente e stampato in ordine.

Alcuni input e output di test inclusi alcuni casi limite:

input   output
ab3c5   aaabbbccccc
a0b3    bbb  
13b1    111b
a13b1   aaa111b
a123b1  aaa111222b
aa2a1b1 aaaaab
  • Una sequenza di caratteri ( [a-zA-Z0-9]+) deve essere seguita dalla sua lunghezza ( [0-9])
  • Solo gli input validi devono essere considerati ( ([a-zA-Z0-9]+[0-9])*)
    • sì, la stringa vuota è un input valido.
  • L'input avviene tramite input standard, output tramite output standard

Questo è il codice golf, il numero di byte determina il vincitore.


@AlexA. Corretta. Ci sono alcuni esolang che mi piace vedere di volta in volta che sono altrimenti penalizzati dal conteggio dei byte. (Sono certamente aperto a suggerimenti sul perché questo potrebbe essere un errore contare in questo modo)

4
@MichaelT Il punteggio per carattere incoraggia fortemente a comprimere il codice sorgente in UTF32, che consente la codifica fino a 4 byte per carattere, ma è completamente illeggibile.
isaacg,

@isaacg fair 'nuff. Modificherò per cambiare in byte. Mi ruminerò su un modo per esprimere lo stile di uno strillo per essere accettabile per le sfide future.

La nostra presentazione dovrebbe essere completata senza errori se l'input è la stringa vuota? Il consenso su meta è che l'output su STDERR può essere ignorato, ma dal momento che lo hai esplicitamente menzionato, devo chiedere.
Dennis,

@Dennis una stringa vuota come input dovrebbe, dovrebbe fermarsi. Non dovrebbe andare in un ciclo infinito o stampare altro testo sull'output standard.

Risposte:


3

Pip, 22 + 1 = 23 byte

Usa la -rbandiera. Si noti che ciò richiede 1) inserire un EOF dopo che l'input (Ctrl-D su Linux, Ctrl-Z su Windows) o 2) reindirizza l'input da qualche altra parte.

(^_@<v)X_@vMa@`\D*\d+`

Spiegazione:

                        a is first line of stdin (from -r flag) and v is -1 (implicit)
              `\D*\d+`  Pattern (regex) object that matches zero or more non-digits
                        followed by at least one digit
            a@          Find all non-overlapping matches in a, returning a list of strings
           M            To that list, map a lambda function:
  _@<v                    Argument sans last character (equivalent to Python a[:-1])
(^    )                   Split into a list of characters
        _@v               Last character of argument
       X                  Repeat each character of the list that many times
                          (String multiplication X, like most operators, works item-wise
                          on lists)
                        Auto-print (implicit)

Il risultato dell'operazione della mappa è in realtà un elenco di elenchi, ma per impostazione predefinita gli elenchi vengono semplicemente concatenati insieme quando stampati, quindi non è necessaria la conversione manuale in stringa.

Esempio, con input a13b1:

Var a gets        "a13b1"
After regex match  ["a13" "b1"]
After map          [["aaa" "111"] ["b"]]
Final output       aaa111b

Pip ha il supporto regex di base a partire da ... 2 giorni fa . Grande tempismo!


Quello funziona (e così fa il padrone) con la -rbandiera. (La domanda specifica che l'input deve provenire da STDIN.)
Dennis,

@Dennis Oops, l'ho perso. Aggiunto flag al conteggio dei byte. Avrei dovuto essere in grado di utilizzare la variabile speciale qinvece di asenza flag extra, ma sembra che ci sia un bug e che chieda l'input due volte.
DLosc,

Finalmente un linguaggio da golf con supporto regex!
Dennis,

@Dennis, ti vedo passare a pip adesso!
Ottimizzatore

8

Perl / Bash 54 40 + 1 = 41 byte

perl -pe's:(\D*\d*)(\d):"\$1=~s/./\$&x$2/egr":ege'

Fondamentalmente è una regex all'interno di una regex. E un po 'di magia.

Spiegazione

La regex esterna /(\D*\d*)(\d)/gestrae ogni gruppo codificato di lunghezza di esecuzione. Catturiamo le cose da ripetere $1e il numero di ripetizioni in $2. Ora sostituiamo ciascuno di questi gruppi con l'espansione di quel gruppo. Per questo, valutiamo il codice "\$1=~s/./\$&x$2/egr" due volte (come dalla /eebandiera sulla sostituzione esterna).

La prima valutazione interpolerà solo il numero di ripetizioni nella stringa - le altre variabili sono protette da una barra rovesciata. Quindi, supponendo l'input a14, ora avremmo il codice $1=~s/./$&x4/egr, che verrà nuovamente valutato.

Questo applicherà la sostituzione al contenuto di $1(il materiale da ripetere a1). La sostituzione corrisponde a ciascun personaggio. . La $&variabile contiene l'intera corrispondenza, che ripetiamo x4volte. Lo facciamo/g lobalmente per ogni corrispondenza ed /restendiamo la stringa sostituita invece di modificare la $1variabile (che è di sola lettura). Quindi il risultato della sostituzione interiore è aaaa1111.

Il -pflag applica la sostituzione a ciascuna riga di input e stampa il risultato.


3
È consuetudine attribuire questo punteggio come soluzione Perl, in cui è sufficiente aggiungere 1 byte per il -pmodificatore. Conto 45 byte. Inoltre, dovresti essere in grado di utilizzare \Dinvece di [a-z], il che ha anche eliminato la necessità di i.
Dennis,

7

CJam, 33 31 27 byte

Uh, la mancanza di espressioni regolari rende questo piuttosto lungo ...

qN+{:XA,s&L\:L>{])~e*[}&X}%

Come funziona

Esaminiamo tutti i caratteri della stringa di input e in ogni iterazione, teniamo traccia dell'ultimo carattere rilevato (iniziando con un carattere vuoto per la prima volta). Quindi controlliamo se il carattere corrente non è numerico e l'ultimo carattere è numerico. In tal caso, ripetiamo ogni carattere precedente (che non è già stato ripetuto), il numero di volte.

(Espansione del codice un po 'obsoleta)

q{                       }%        e# Read the input (q) and loop through each character
  L                                e# Put variable L (initially empty character) on stack
   A,                              e# Put variable A (equals 10) and create an array 0..9
     s                             e# Convert the array to string "0123456789"
      &                            e# Do a set intersect b/w previous char and 0-9 string
                                   e# If numeric, it gives 1 char string, otherwise 0
       \:LA,s&                     e# Swap to bring current character on top. Store it in L
                                   e# and do the same set intersect with it
              >                    e# Means we are checking that current char is non-numeric
                                   e# and previous numeric
               {      }&           e# Run this block if above is true
                ])~                e# Wrap everything not already repeated in an array and
                                   e# take out the last character and convert it to integer.
                                   e# This is the run length of the preceding string
                   e*              e# Repeat each character in the string, run length times
                     [             e# Start a new array to help when next run length is found
                        L          e# Restore the current character back on stack to be used
                                   e# in next iteration
                           )~e*    e# The last string-run-length pair is not decoded..
                                   e# So we do that now

Provalo online qui


Apprezzo la dimostrazione del problema causato dal qualificatore di byte. Grazie. Sto pensando un po 'a come formulare la qualifica in modo tale che le lingue in cui una singola istruzione è un carattere multi-byte non vengano penalizzate per quello stile di linguaggio senza consentire alla codifica UTF che hai mostrato di ottenere tramite la scappatoia. PS Mi piace molto vedere la ripartizione algoritmica che fornisci.

6

rs , 43 71 caratteri

Bene, questo è cambiato molto velocemente. Numeri stupidi ...

(\d)(\D)/\1 \2
+(\w)(\w+?)(\d)(?= |$)/\1\3 \2\3
(\w)(\d)/(\1)^^(\2)
 /

Provalo qui!

Versione originale (non ha funzionato con input simili 123):

+(\D)(\D+)(\d)/\1\3\2\3
(\D)(\d)/(\1)^^(\2)

Spiegazione

La prima riga posiziona gli spazi tra le serie contenenti numeri, ad esempio trasformandoli a313in a3 13.

La seconda linea espande continuamente le codifiche compressi come aa5a a5a5.

La terza riga converte ogni istanza a5in aaaaautilizzando l' operatore di ripetizione .

L'ultima riga rimuove gli spazi.


Come gestisce a123b1?
Ottimizzatore

@Optimizer Non bene. Devo modificarlo un po '...
Kirbyfan64sos,

@Optimizer fisso.
Kirbyfan64sos,

5

Javascript ( ES6 ), 86 83 byte

alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>b.replace(/./g,y=>y.repeat(c))))

ha commentato:

alert( // output final result
    prompt(). // take input
    replace(/(.+?)(\d)(?!\d)/g, // replace ungreedy capture group of any characters 
                                // followed by a digit (captured)
                                // and not followed by a digit (negative lookahead)
        (a, b, c)=> // replace with a function
            b.replace(/./g, // replace all characters in b
                y=>y.repeat(c) // with that character repeated c times
            )
    )
)

Non alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>Array(c+1).join(b)))fare lo stesso? È lungo solo 71 byte.
Ismael Miguel,

@IsmaelMiguel che funzionerebbe solo se ci fosse un singolo carattere prima della cifra. La comprensione dell'array gestisce la ripetizione di ogni carattere singolarmente.
nderscore,

Prova Array(6).join('12')e tornerà '1212121212'.
Ismael Miguel,

Questo funziona: alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>Array(-~c).join(b)))(stessi 71 byte, testato su es6fiddle.net/ia7gocwg )
Ismael Miguel,

1
Ho trovato un modo diverso (ovvio) per dire 3 byte: D
nderscore,

4

CJam, 27 25 byte

r_'A+1>.{64&1$>{])~f*o}&}

Provalo online nell'interprete CJam .

Come funziona

r_                        e# Read a token from STDIN and push a copy.
  'A+                     e# Append the character A to the copy.
     1>                   e# Discard the first character of the copy.
       .{               } e# For each character C of the input string and the
                          e# corresponding character D of the copy:
         64&              e#   Take the bitwise and of D and 64. This pushes @
                          e#   if D is a letter and NUL if it is a digit.
            1$>           e#   Compare the result to a copy of C. This pushes 1
                          e#   if and only if D is a letter and C is a digit.
               {      }&  e#   If the result was 1, do the following:
                ]         e#     Wrap the stack in an array.
                 )~       e#     Pop and evaluate the last character.
                   f*     e#     Repeat each char in the array that many times.
                     o    e#     Print all characters.

3

Pyth, 33 32 28 byte

ssmm*vedkPdPcz-hMJf<@zT\=UzJ

Provalo online: cablaggio dimostrativo o di prova

Spiegazione

Spiegherò il codice usando l'input di esempio aa1a23b2. Spero che questo sia un po 'più facile da seguire che senza.

                               implicit: z = input string = 'aa1a23b2'
                         Uz    the indices of z: [0, 1, 2, 4, 5, 6, 7]
                  f            filter for indices T, which satisfy:
                   <@zT\=        z[T] < "="
                               this gives us the list of indices [2, 4, 5, 7], 
                               which correspond to digits in z. 
                 J             assignment, J = [2, 4, 5, 7]
               hMJ             increment all element in J: [3, 5, 6, 8]
              -            J   and remove the elements of J:
                                 [3, 5, 6, 8] - [2, 4, 5, 7] = [3, 6, 8]
            cz                 split z at these indices: ['aa1', 'a23', 'b2', '']
           P                   remove last element: ['aa1', 'a23', 'b2']
  m                            map each string d to:
   m     Pd                      map each string k of d-without-last-char to:
     ved                           int(last element of d)
    *   k                          * k
                               this creates [['a', 'a'], ['aaa', '222'], ['bb']]
 s                             sum the lists: ['a', 'a', 'aaa', '222', 'bb']
s                              sum the strings: 'aaaaa222bb'


2

JavaScript 112

alert(prompt().replace(/.*?\d+/g,function(m){for(i=n=m.length-1,o="";i--;){j=m[n];while(j--)o=m[i]+o}return o}))


2

Python 2.7, 98 byte

import re
print"".join(c*int(m[-1])for m in 
re.findall(r".+?\d(?!\d)",raw_input())for c in m[:-1])

Questo fa semplicemente una semplice ricerca regex per le cifre che non sono seguite da una cifra, quindi esegue l'aritmetica di stringa su ciascun gruppo e li unisce tutti insieme.


È possibile salvare 2 byte passando da Python 2 a 3. raw_inputdiventa inputma printnecessita di parentesi.
Alex A.

Vero, ma preferisco giocare a golf in Python 2.7.
ricorsivo

1

Julia, 105 99 95 87 byte

s->join([join([string(b)^(int(p[end])-48)for b=chop(p)])for p=matchall(r"\D*\d*\d",s)])

Questo crea una funzione senza nome che accetta una stringa come input a restituisce una stringa. Per chiamarlo, dagli un nome, ad es f=s->....

Qui vengono utilizzate due comprensioni di array, una nidificata nell'altra. La comprensione esterna agisce su ogni corrispondenza della stringa di input rispetto all'espressione regolare\D*\d*\d . La comprensione interiore ripete ogni carattere della partita in base alla cifra finale. Gli elementi dell'array interno sono uniti in una stringa, quindi l'array esterno è un array di stringhe. Questi vengono uniti e restituiti.

In Julia, le stringhe possono essere trattate come matrici di caratteri. Tuttavia, si noti che i tipi Chare Stringin Julia non hanno gli stessi metodi definiti; in particolare, non esiste un metodo per la ripetizione utilizzando ^per i caratteri. Questo utilizza una soluzione alternativa contorta:

  • Passa sopra la stringa omettendo l'ultimo carattere, che viene rimosso usando chop().
  • Converti il ​​carattere corrente in una stringa usando string().
  • Converti la cifra finale, che è anche un carattere, in un numero intero. Tuttavia, si noti che, ad esempio, int('4')non restituisce 4. Piuttosto, restituisce il punto di codice, che in questo caso è 52. In questo modo è possibile sottrarre 48 per recuperare il numero intero effettivo.
  • Ripetere string(b)secondo int(p[end]) - 48.

Esempi:

julia> f("ab3c5")
"aaabbbccccc"

julia> f("a0b3")
"bbb"

julia> f("13b1")
"111b"

1

Python 3, 148 144 136 135 byte

w,o,r,d=''.join,'',[],[]
for c in input()+' ':
 if'/'<c<':':d+=[c]
 elif d:o+=w(x*int(w(d))for x in r);r=[c];d=[]
 else:r+=[c]
print(o)

Grazie a Pietu1998 e mbomb007 per i suggerimenti.

Python 2, 161 151 147 139 138 byte

Forse oggi è stata solo una lunga giornata di lavoro, ma non posso per la vita di me capire come giocare a golf ..

w,o,r,d=''.join,'',[],[]
for c in raw_input()+' ':
 if'/'<c<':':d+=[c]
 elif d:o+=w(x*int(w(d))for x in r);r=[c];d=[]
 else:r+=[c]
print o

3
Passare a Python 3 salva un paio di byte ( raw_fuori, parentesi in print). len(d)>0può essere sostituito dal dfatto che una lista vuota è falsa e una lista non vuota è vera. list(...)può andare direttamente al for. Le parentesi quadre in w([...])non sono necessarie poiché è l'unico argomento. È possibile rimuovere lo spazio in ) for. Sono tutte le cose minori che ho escogitato finora.
PurkkaKoodari,

@ Pietu1998 Grazie per l'aiuto!
Kade,

Senza cambiare troppo il tuo approccio, puoi sbarazzartene list()poiché le stringhe sono iterabili. È possibile utilizzare w=r=''. Se sei disposto a cambiarlo molto, vedi la mia soluzione. :)
ricorsivo

if c.isdigit()può diventare if'/'<c<':', se non sbaglio.
DLosc,

@DLosc grazie, sembra funzionare.
Kade,

0

Java 7, 175 byte

String c(String s){String r="",a[];for(String x:s.split("(?<=(\\d)(?!\\d))")){a=x.split("");for(int i=0,j,l=a.length-1;i<l;i++)for(j=0;j++<new Short(a[l]);r+=a[i]);}return r;}

La sfida è più difficile di quanto sembri, imo ..

Codice non testato e test:

Provalo qui.

class M{
  static String c(String s){
    String r = "",
           a[];
    for(String x : s.split("(?<=(\\d)(?!\\d))")){
      a = x.split("");
      for(int i = 0, j, l = a.length-1; i < l; i++){
        for(j = 0; j++ < new Short(a[l]); r += a[i]);
      }
    }
    return r;
  }

  public static void main(String[] a){
    System.out.println(c("ab3c5"));
    System.out.println(c("a0b3"));
    System.out.println(c("13b1"));
    System.out.println(c("a13b1"));
    System.out.println(c("a123b1"));
    System.out.println(c("aa2a1b1"));
    System.out.println(c("123"));
  }
}

Produzione:

aaabbbccccc
bbb
111b
aaa111b
aaa111222b
aaaaab
111222
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.