Termina le schede contro la guerra spaziale


24

Termina le schede contro la guerra spaziale

Pertanto, si è discusso molto sull'opportunità di utilizzare schede o spazi per indentare / formattare il codice. Puoi aiutare l'università a risolvere la controversia, adottando un metodo di formattazione unico incredibilmente pazzo .


Il tuo compito è scrivere un programma o una funzione completa che espanda tutte le schede in quattro spazi. Quindi sostituisce una sequenza di n spazi iniziali con "/ (n - due stelle qui) /". Riceverai input su più righe in qualsiasi formato ragionevole (array di stringhe a stringa singola per ogni nuova riga. Array a colonne ecc.)

Input del campione rubato senza vergogna . Si noti che poiché le schede si espandono automagicamente in quattro spazi su SE, lo rappresento come il carattere "^", ma è necessario gestire anche le schede (punto di codice 0x09). Tutti i caratteri "^" rappresentano una tabulazione.

Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
    Not zero so multiply by 256 again to get 65536
    [>++++<-]>[<++++++++>-]<[>++++++++<-]
    +>[>
        # Print "32"
        ++++++++++[>+++++<-]>+.-.[-]<
    <[-]<->] <[>>
        # Print "16"
        +++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
    # Print "8"
    ++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
^this is preceded by a tab
^^two tabs
^^^three tabs etcetera! 

Uscita campione

Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
/**/Not zero so multiply by 256 again to get 65536
/**/[>++++<-]>[<++++++++>-]<[>++++++++<-]
/**/+>[>
/******/# Print "32"
/******/++++++++++[>+++++<-]>+.-.[-]<
/**/<[-]<->] <[>>
/******/# Print "16"
/******/+++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
/**/# Print "8"
/**/++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
/**/this is preceded by a tab
/******/two tabs
/**********/three tabs etcetera! 

Poiché l'università ha bisogno di spazio per scaricare sia Vim che Emacs, ti è concesso pochissimo spazio di archiviazione per il tuo codice. Quindi questo è e vince il codice più corto. Si può presumere che l'input sia ben formato e che le linee con meno di quattro spazi (dopo la sostituzione delle schede) possano comportare un comportamento indefinito.

disconoscimento

Questa "eccellente" strategia di formattazione è stata gentilmente concessa da Geobits ed è riprodotta con il suo permesso. Nessun programmatore è stato danneggiato durante la produzione di questa sfida.


1
Le schede si verificano solo all'inizio delle righe (ovvero come rientro)? Le linee possono avere rientri misti (tabulazioni + spazi)?
Lynn,

20
Qualcuno invia una risposta scritta in Whitespace .
GuitarPicker,

2
Dovremmo considerare le linee che iniziano con /*, o può essere assunto come un "input ben formato"? Un file sorgente C ++ sarebbe stato un test migliore, perché il suo commento su più /* */righe potrebbe spezzare alcune risposte che sostituiscono il primo e l'ultimo degli spazi iniziali con un /, e quindi procedere con il riempimento degli spazi *.
seshoumara,

1
La guerra è finita: medium.com/@hoffa/… (A meno che tu non stia programmando in C, a quanto pare.)
Becher

1
@RohanJhunjhunwala Quindi ora faccio di nuovo la mia prima domanda, dato che non si trattava di codice compilabile. Immagina lo stesso /* */codice C ++, ma questa volta all'inizio della riga. Secondo le vostre specifiche dovrebbe essere lasciato così com'è. Qui la trappola è, e ha già individuato risposte sbagliate, che una regex come dire /\** /usata per riempire quegli spazi tra // con asterischi trasformerebbe la linea in /***/. Ho visto anche questa conversione /*//*/. Presumo che entrambi siano errati.
seshoumara,

Risposte:


2

V , 21 , 20 byte

Íô/    
Î^hr/hv0r*r/

Provalo online!

Questo è letteralmente solo una porta diretta della mia risposta di Vim. Le notevoli differenze:

  • Il Ícomando (sostituto globale) riempie automaticamente il /gflag, che salva due byte

  • ô è identico a \t

  • ÎÈ un mnemonico per :%norm, e riempie anche lo spazio necessario tra :%norme l'insieme dei tasti.

  • Il ritorno finale del carrello alla fine viene aggiunto implicitamente.


27

Vim, 37, 34, 33, 32 byte

:%s/\t/    /g|%norm ^hr/hv0r*r/

Provalo online!

Si noti che ciò richiede un ritorno a capo (invio) in vim, sebbene non nell'interprete online.

Questo utilizza l'interprete V perché è retrocompatibile. Una soluzione molto semplice.

Ecco una gif che ti consente di vedere la soluzione accadere in tempo reale. Questo utilizza una versione leggermente più vecchia e ho aggiunto alcuni tasti extra per farlo funzionare più lentamente in modo da poter vedere cosa succede:

inserisci qui la descrizione dell'immagine

Ed ecco la spiegazione di come funziona:

:%s/\t/    /g           "Replace every tab with 4 spaces
|                       "AND
%norm                   "On every line:
      ^                 "  Move to the first non-whitespace char
       h                "  Move one character to the left. If there is none, the command will end here.
         r/             "  Replace it with a slash
           h            "  Move to the left
            v0          "  Visually select everything until the first column
              r*        "  Replace this selection with asterisks
                r/      "  Replace the first character with a slash

Avrei fatto +1 per l'uso gma poi hai modificato per non usare g: / +1 comunque: D
Downgoat

@downgoat Haha, grazie! In realtà sono molto più orgoglioso della versione senza :gperché abusa di una funzionalità meno conosciuta: il normcomando viene annullato se ^F<space>fallisce. Quindi :%norm ^F<space>fooè essenzialmente la stessa cosa dei :g/^ /norm foodivertenti hack di Vim. : D
DJMcMayhem

eh, ho pensato che ^ F fosse usato per postare lo schermo. ha un comportamento diverso all'interno norm?
Downgoat,

1
@downgoat Haha, non è ^F, non è <C-f>fondamentale Sciocco Vim notazione. In questo caso ^, passa al primo carattere non di spazi bianchi e F<space>Quale è il primo spazio dietro il cursore.
DJMcMayhem

ohhh, ora ha molto più senso> _>
Downgoat,

11

Perl, 41 byte

s,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,

Corri con la -pbandiera, in questo modo:

perl -pe 's,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,'
#     ↑   └───────────────────┬───────────────────┘
#     1 byte               40 bytes

Sostituisci con una scheda (in Bash, prova a digitare Control-V Tab.)


1
Il modo in cui ha perlsostituito quel backreference sul posto, vorrei sedanche quello.
seshoumara,

7

Cheddar , 60 57 56 byte

Salvato 3 byte grazie a @Conor O'Brien

@.sub(/\t/g," "*4).sub(/^ +/gm,i->"/"+"*"*(i.len-2)+"/")

Vorrei che Cheddar avesse una migliore formattazione delle stringhe.

Provalo online!

Spiegazione

Questa è una funzione @è una proprietà funzionalizzata rappresenta (es. ruby &:) che ti permette di fare cose come: `ar.map (@. head (-1))

@                      // Input
 .sub( /\t/g, " "*4)   // Replace tabs with four spaces
 .sub(
   /^ +/gm,            // Regex matches leading spaces
   i ->                // i is the matched leading spaces
     "/"+              // The / at the beginning
     "*"*(i.len-2)+    // Repeat *s i-2 times
     "/"                // The / at the end
 )

Se non hai familiarità con regex il:

/^ +/gm

questo fondamentalmente corrispondeva a uno o più ( +) spazi ( ) all'inizio ( ^) di ogni ( g) linea ( m).


le linguette letterali funzionano nelle regex del cheddar? inoltre, è /^ +/sufficiente una regex, poiché possiamo presumere che gli spazi iniziali saranno lunghi almeno 4.
Conor O'Brien,

@ ConorO'Brien Credo di si, ma non ho ancora testato
Downgoat,

Le schede dovrebbero essere sostituite prima della trasformazione.
Conor O'Brien,

@ ConorO'Brien oh> _> L'ho avuto in quel modo originariamente e poi l'ho cambiato
Downgoat

6

Mathematica, 97 byte

a=StringReplace;a[a[#,"\t"->"    "],StartOfLine~~b:" "..:>"/"<>Table["*",StringLength@b-2]<>"/"]&

Funzione anonima. Accetta una stringa come input e restituisce una stringa come output.


5

Python 3, 124 byte

Usa un buon vecchio regex.

import re
lambda I:re.sub('^\s*(?m)',lambda m:'/'+'*'*len(m.group()[:-2])+'/',re.sub('\t+',lambda g:' '*4*len(g.group()),I))

Ideone esso!


4

Java 210 207 byte

Questa è la soluzione di riferimento che la implementa in modo ingenuo.

void a(String[]a){for(String s:a){s=s.replaceAll("\t", "    ");String x,y="";int j,i=s.length()-(x=s.replaceAll("^\\s+", "")).length();if(i>3){y="/";for(j=0;j++<i-1;)y+="*";y+="/";}System.out.println(y+x);}}

6
Vim: 37 byte, Cheddar: 65 byte, JavaScript: 75 byte, quindi c'è Java a 210 byte: P perché non sono sorpreso
Downgoat

1
Codice molto conciso in java: P
Rohan Jhunjhunwala

È possibile modificare l'ultimo ciclo for per salvare 1 byte: for(int j=0;++j<i-1;). Inoltre, puoi rimuovere il int precedente je inserirlo dopo l'int già presente:int i=s.length()-(x=s.replaceAll("^\\s+", "")).length(),j;
Kevin Cruijssen,

non può essere un lambda a radere byte usando (a) -> {...}?
bunyaCloven

Almeno è ancora leggibile e non ha bisogno di ulteriori commenti: o)
René

3

JavaScript ES6, 75 byte

s=>s.replace(/\t/g,"    ").replace(/^ +/gm,k=>`/${"*".repeat(k.length-2)}/`)

Sostituisci \tcon una scheda letterale nel tuo codice.


3

Java, 185 184 167 152 byte

S->S.map(s->{s=s.replace("\t","    ");String t=s.replaceAll("^ +","");int n=s.length()-t.length();if(n>3){s="/";for(;n-->2;)s+="*";s+="/"+t;}return s;})

Data la definizione molto ampia di array di stringhe fornita nel post iniziale, l'ho usata Stream<String>per consentire un conseguente risparmio di byte.

Ho usato tecniche diverse rispetto al RI per raggiungere lo stesso obiettivo. L'algoritmo stesso è piuttosto lo stesso.

Test e non golfati :

import java.util.Arrays;
import java.util.stream.Stream;

public class Main {

  public static void main(String[] args) {
    StringStreamTransformer sst = lines -> lines.map(line -> {
      line = line.replace("\t","    ");
      String trimmed = line.replaceAll("^ +", "");
      int startingSpaces = line.length() - trimmed.length();
      if (startingSpaces > 3) {
        line = "/";
        for(;startingSpaces > 2; startingSpaces--) {
          line += "*";
        }
        line += "/" + trimmed;
      }
      return line;
    });


    Stream<String> lines = Arrays.stream(new String[]{
      "lots of spaces and tabs after\t\t    \t\t         \t\t\t\t\t",
      "no space",
      " 1 space",
      "  2 spaces",
      "   3 spaces",
      "    4 spaces",
      "     5 spaces",
      "      6 spaces",
      "       7 spaces",
      "        8 spaces",
      "\t1 tab",
      "\t\t2 tabs",
      "\t\t\t3 tabs"
    });
    sst.map(lines).map(s -> s.replace(" ", ".").replace("\t","-")).forEach(System.out::println);


  }
}

2

Retina , 25 byte

La \tdeve essere sostituito con un carattere di tabulazione attuale (0x09).

\t
4$* 
%`^  ( +)
/$.1$**/

Provalo online!

Spiegazione

\t
4$* 

Sostituisci ogni scheda con quattro spazi.

%`^  ( +)
/$.1$**/

Trasforma ciascuna riga separatamente ( %) abbinando gli 2+Nspazi all'inizio della riga e sostituendoli con /.../dove ...sono le Ncopie* .



2

SED (56 + 1 per -r) 57

s/⇥/    /g;tr;:r;s,^ ( *) ,/\1/,;T;:l;s,^(/\**) ,\1*,;tl

Dove si trova una scheda
1. sostituisce le schede con spazi.
2. sostituisce il primo e l'ultimo spazio iniziale con /.
3. sostituisce il primo spazio dopo /e 0+ *s con a *fino a quando non c'è corrispondenza.


Dato che sed è specificato, non sono necessarie virgolette singole attorno al codice, lo stesso con la rimozione di -r '' dalle altre risposte sed, poiché è possibile considerare lo script come archiviato in un file sorgente con cui si esegue -f. Eventuali flag aggiuntivi utilizzati come n o r devono essere conteggiati come un byte ciascuno. Quindi qui, risparmi 2 byte.
seshoumara,

Questo è quello che ho pensato, ma ne voglio la certezza. Grazie.
Riley,

Il ;dopo il comando t non è necessario neanche. Per quanto riguarda il codice stesso, è necessario un ^ all'inizio del terzo scomando, altrimenti un input come questo "3/5" viene trasformato in "3 / * 5". Nel primo scomando hai effettivamente una scheda lì, ma non è mostrata correttamente e fuorviante, quindi usa \ t o specifica dopo, quel carattere era una scheda.
seshoumara,

@seshoumara Grazie, sto provando a postare dal mio telefono ... Non è la cosa più semplice da fare.
Riley,

Penso di aver passato più tempo a modificare questa risposta di tutte le altre messe insieme. Grazie per l'aiuto!
Riley

1

L'università dovrebbe prendere in considerazione la possibilità di concedere un po 'più di spazio ai programmi in Emacs Lisp (o di default a tabifyeuntabify da solo), mentre ottengono ancora più dettagliato di Java. Dovrebbe anche prestare molta attenzione agli studenti (o agli insegnanti) la cui dimensione di identificazione è inferiore a quattro o che capita di programmare in un linguaggio non simile al C.

La seguente soluzione ha 206 byte

(lambda (b e)(let((tab-width 4))(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))))))

Supponendo che tab-widthnon debba essere impostato in modo esplicito, possiamo salvarne 20.

(lambda(b e)(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2))))))))

E la versione ungolf sarebbe simile a questa

(defun end-tab-war (beg end)
  (let ((tab-width 4))
    (untabify beg end)
    (goto-char beg)
    (while (re-search-forward "^ +" end t)
      (replace-match
       (format
        "/%s/"
        (apply 'concat
               (mapcar (lambda(x) "*")
                       (number-sequence 1
                                        (- (length (match-string 0))
                                           2)))))))))

Per prima cosa untabifyla regione prima di saltare al suo inizio. Quindi, mentre vediamo uno spazio all'inizio di una riga, lo sostituiamo con un commento lungo quanto detto spazio. Per l'esattezza, il commento da inserire è costruito da

 (format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))

che a sua volta occupa 97 byte. Una soluzione più breve per copiare alcune stringhe n volte è molto apprezzata.


1

Rubino, 52 47 + 1 (bandiera p) = 48 byte

Modifica : risparmiato 5 byte interi, grazie a Value Ink

ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'

1
Puoi usare il pflag per trarre vantaggio dal fatto che (g) sub modifica $_e quindi cambia il valore stampato? ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'
Value Ink

Grazie, non sapevo che (g)subsenza il botto è possibile modificare $_qui.
Michau,

1

GNU sed, 66 64 + 1 (flag r) = 65 byte

Modifica: 1 byte in meno grazie al suggerimento di Riley .

s/\t/    /g
s,^ ( *) ,/\1\n,
:
s,^(/\**) ( *\n),\1*\2,
t
s,\n,/,

Esegui: sed -rf formatter.sed input_file

La ragione per separare con \ngli spazi iniziali dal resto del testo su quella riga, è perché altrimenti una linea C ++ che inizia con un commento come questo /* */verrebbe trasformata in /*****/una linea più semplice 4 simile s,^(/\**) ,\1*,o pari s,^(/\**) ( */),\1*\2,. Poiché sed esegue lo script per ogni riga di input, no \nviene introdotto nello spazio modello durante la lettura.


È possibile salvare un byte non inserendo la chiusura /fino a quando non si sostituisce il \n. Questo ti evita di abbinarlo alla riga 4.
Riley

@Riley Buona cattura. Aggiornato il codice.
seshoumara,

Puoi salvarne un altro sostituendolo \tcon un carattere di tabulazione.
Riley,

@Riley Questo è vero, ma dal momento che non verrà stampato come una scheda qui, sono in dubbio. Lo terrò presente per future risposte sed con conteggi di byte più competitivi.
seshoumara,
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.