Termine as abas contra a guerra espacial


24

Termine as abas contra a guerra espacial

Portanto, houve um grande debate sobre o uso de guias ou espaços para recuar / formatar o código. Você pode ajudar a universidade a resolver a disputa, adotando um método único e incrivelmente louco de formatação.


Seu trabalho é escrever um programa ou função completo que expanda todas as guias em quatro espaços. E então substitui uma série de n espaços à esquerda por "/ (n - duas estrelas aqui) /". Você receberá entrada em várias linhas em qualquer formato razoável (matriz de cadeias de caracteres única para cada nova linha. Matriz colunar etc.)

Entrada de amostra roubada descaradamente . Observe que, como as guias são expandidas automaticamente para quatro espaços no SE, eu o represento como o caractere "^", mas você também deve manipular as guias (codepoint 0x09). Todos os caracteres "^" representam uma tabulação.

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! 

Saída de amostra

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! 

Como a universidade precisa de espaço para baixar o Vim e o Emacs, você tem muito pouco espaço de armazenamento para o seu código. Portanto, este é o e o código mais curto vence. Você pode assumir que a entrada é bem formada e as linhas com menos de quatro espaços (após a substituição das guias) podem resultar em um comportamento indefinido.

aviso Legal

Essa estratégia de formatação "excelente" veio como cortesia do Geobits e é reproduzida com sua permissão. Nenhum programador foi prejudicado durante a produção deste desafio.


11
As guias ocorrerão apenas no início das linhas (ou seja, como recuo)? As linhas podem ter recuo misto (tabulações + espaços)?
Lynn

20
Alguém envie uma resposta escrita em espaço em branco .
GuitarPicker

2
Devemos considerar as linhas que começam com /*, ou isso pode ser assumido como não uma "entrada bem formada"? Um arquivo de origem C ++ teria sido um teste melhor, porque seu comentário de várias linhas /* */possivelmente quebraria algumas respostas que substituem o primeiro e o último dos espaços iniciais por um /e, em seguida, prossiga para preencher espaços com *.
seshoumara 1/09/16

11
A guerra terminou: medium.com/@hoffa/... (A menos que você está programando em C, aparentemente.)
copo

11
@RohanJhunjhunwala Então agora faço novamente a minha primeira pergunta, já que não se tratava de código compilável. Imagine o mesmo /* */código C ++, mas desta vez no início da linha. De acordo com suas especificações, ele deve ser deixado como está. Aqui a armadilha é, e já encontrou respostas erradas, que um regex como o dizer /\** /usado para preencher esses espaços entre // com asteriscos transformaria a linha /***/. Eu já vi essa conversão também /*//*/. Presumo que ambos estejam incorretos.
seshoumara 1/09/16

Respostas:


2

V , 21 , 20 bytes

Íô/    
Î^hr/hv0r*r/

Experimente online!

Esta é literalmente apenas uma porta direta da minha resposta vim. As diferenças notáveis:

  • O Ícomando (substituto global) preenche automaticamente o /gsinalizador, que salva dois bytes

  • ô é idêntico a \t

  • ÎÉ um mnemônico para :%norm, e também preenche o espaço necessário entre :%norme o conjunto de teclas.

  • O retorno de carro à direita no final é adicionado implicitamente.


27

Vim, 37, 34, 33, 32 bytes

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

Experimente online!

Observe que isso requer um retorno de carro à direita (enter) no vim, embora não no intérprete online.

Isso usa o intérprete V porque é compatível com versões anteriores. Uma solução muito simples.

Aqui está um gif que permite ver a solução acontecer em tempo real. Isso usa uma versão um pouco mais antiga, e eu adicionei algumas teclas extras para torná-la mais lenta, para que você possa ver o que acontece:

insira a descrição da imagem aqui

E aqui está a explicação de como funciona:

:%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

Eu ia +1 para usar g, mas então você editado para não usar g: / +1 de qualquer maneira: D
Downgoat

@downgoat Haha, obrigado! Na verdade, estou muito mais orgulhoso da versão sem :gporque ela abusa de um recurso menos conhecido: o normcomando é cancelado se ^F<space>falhar. Então, :%norm ^F<space>fooé essencialmente a mesma coisa que :g/^ /norm foodivertidos hacks do Vim. : D
DJMcMayhem

hein, pensei que ^ F fosse usado para postar a tela. tem comportamento diferente por dentro norm?
Downgoat 31/08/16

11
@downgoat Haha, não é ^F, não <C-f>notação chave parva Vim. Nesse caso ^, pule para o primeiro caractere que não é um espaço em branco e F<space>Qual é o primeiro espaço atrás do cursor.
DJMcMayhem

ohhh, que faz muito mais sentido agora> _>
Downgoat

11

Perl, 41 bytes

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

Corra com a -pbandeira, assim:

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

Substitua por uma guia (no Bash, tente digitar Control-V Tab.)


11
A maneira como perlsubstituímos essa referência no local, eu gostaria sedque tivesse isso também.
seshoumara 1/09/16

7

Queijo Cheddar , 60 57 56 bytes

Guardado 3 bytes graças a @Conor O'Brien

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

Eu gostaria que o Cheddar tivesse melhor formatação de string.

Experimente online!

Explicação

Esta é uma função. @é uma propriedade funcionalizada representa (por exemplo, ruby's &:), permitindo que você faça coisas como: `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 você não está familiarizado com o regex, o:

/^ +/gm

isso basicamente corresponde a um ou mais ( +) espaços ( ) no início ( ^) de cada ( g) linha ( m).


guias literais funcionam em expressões regulares de queijo cheddar? também /^ +/é suficiente como uma expressão regular, pois podemos assumir que os espaços iniciais terão pelo menos 4 de comprimento.
Conor O'Brien

@ ConorO'Brien Eu acredito que eles fazem, mas eu não testei
Downgoat

As guias devem ser substituídas antes da transformação.
Conor O'Brien

@ ConorO'Brien oh> _> Eu tinha esse jeito originalmente e depois mudei
Downgoat

6

Mathematica, 97 bytes

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

Função anônima. Pega uma string como entrada e retorna uma string como saída.


5

Python 3, 124 bytes

Usa boa e velha 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 it!


4

Java 210 207 bytes

Esta é a solução de referência que a implementa ingenuamente.

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 bytes, Cheddar: 65 bytes, JavaScript: 75 bytes, então não há Java em 210 bytes: P por que não estou surpreso
Downgoat

11
Código muito conciso em java: P
Rohan Jhunjhunwala

Você pode alterar o último loop for para salvar 1 byte: for(int j=0;++j<i-1;). Além disso, você pode remover o int antes j, e colocá-lo após a já presente int:int i=s.length()-(x=s.replaceAll("^\\s+", "")).length(),j;
Kevin Cruijssen

não pode ser um lambda raspar bytes usando (a) -> {...}?
precisa saber é o seguinte

Pelo menos ainda é legível e não precisa de mais comentários: o)
René

3

JavaScript ES6, 75 bytes

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

Substitua \tpor uma guia literal no seu código.


3

Java, 185 184 167 152 bytes

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

Dada a definição muito vaga de array de strings dada no post inicial, usei Stream<String> que permite algumas economias de bytes consequentes.

Usei técnicas diferentes das do RI para alcançar o mesmo objetivo. O algoritmo em si é bastante o mesmo.

Testando e não destruído :

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 bytes

o \t deve ser substituído por um caractere de tabulação real (0x09).

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

Experimente online!

Explicação

\t
4$* 

Substitua cada guia por quatro espaços.

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

Transforme cada linha separadamente ( %) combinando 2+Nespaços no início da linha e substituindo-a por /.../onde ...estão as Ncópias de *.



2

SED (56 + 1 para -r) 57

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

Onde está uma guia
1. substitui as guias por espaços.
2. substitui o primeiro e o último espaço à esquerda por /.
3. substitui o primeiro espaço depois /e 0+ *s por um *até que não haja correspondência.


Como sed é especificado, não são necessárias aspas simples no código, o mesmo que remover -r '' de suas outras respostas sed, porque você pode considerar o script como sendo armazenado em um arquivo de origem com o qual você executa -f. Quaisquer sinalizadores extras usados ​​como n ou r devem ser contados como um byte cada. Assim, aqui, você salva 2 bytes.
seshoumara 1/09/16

Foi o que pensei, mas quero ter certeza. Obrigado.
Riley

O ;comando após o t também não é necessário. Quanto ao código em si, você precisa de um ^ no início do terceiro scomando, caso contrário, uma entrada como esta "3/5" é transformada em "3 / * 5". No primeiro scomando, você realmente tem uma guia lá, mas ela não é mostrada e enganosa corretamente; portanto, use \ t ou especifique depois, que char era uma guia.
seshoumara 1/09/16

@seshoumara Obrigado, estou tentando postar no meu telefone ... Não é a coisa mais fácil de fazer.
Riley

Acho que passei mais tempo editando esta resposta do que todas as outras juntas. Obrigado pela ajuda!
Riley

1

A universidade deve considerar permitir um pouco mais de espaço para programas no Emacs Lisp (ou usar como padrão tabifyeuntabify sozinho), pois eles ficam ainda mais detalhados que o Java. Também deve prestar muita atenção aos alunos (ou professores) cujo tamanho de identificação é menor que quatro ou que codificam em algum idioma não-C.

A solução a seguir possui 206 bytes

(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)))))))))

Supondo que tab-widthnão precise ser definido explicitamente, podemos salvar 20 deles.

(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 a versão não-gasta ficaria assim

(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)))))))))

Nós primeiro untabifya região antes de pular para o seu início. Então, enquanto vemos o espaço em branco no início de uma linha, substituí-lo por um comentário que contenha o espaço em branco. Para ser exato, o comentário a ser inserido é construído por

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

que ocupa 97 bytes. Uma solução mais curta para copiar algumas strings n vezes é muito apreciada.


1

Ruby, 52 47 + 1 (sinalizador p) = 48 bytes

Editar : salvou 5 bytes inteiros, graças ao Value Ink

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

11
Você pode usar o psinalizador para aproveitar o fato de que (g) submodifica $_e, portanto, altera o valor impresso? ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'
Value Ink

Obrigado, eu não sabia que (g)subsem bang pode modificar $_aqui.
Michau

1

GNU sed, 66 64 + 1 (sinalizador r) = 65 bytes

Edit: 1 byte a menos, graças à sugestão de Riley .

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

Corre: sed -rf formatter.sed input_file

A razão para separar com \nos espaços iniciais do restante do texto nessa linha é porque, caso contrário, uma linha C ++ iniciada com um comentário como esse /* */seria transformada em /*****/uma linha 4 mais simples, s,^(/\**) ,\1*,igual ou até mesmo s,^(/\**) ( */),\1*\2,. Como o sed executa o script para cada linha de entrada, nenhum \né introduzido no espaço do padrão na leitura.


Você pode salvar um byte não colocando o fechamento /até substituir o \n. Isso evita que você ter que fazê-lo em linha 4.
Riley

@Riley Boa captura. Atualizado o código.
seshoumara 1/09/16

Você pode salvar outro substituindo \tpor um caractere de tabulação.
Riley

@Riley Isso é verdade, mas como não será impresso como uma guia aqui, estou em dúvida. Lembrarei disso para futuras respostas sed com contagens de bytes mais competitivas.
seshoumara 02/02
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.