Analisar os comentários do meu código esotérico

30

No início desta semana, aprendemos sobre como formatar idiomas esotéricos para comentar. Hoje, vamos fazer o inverso disso. Preciso que você escreva um programa ou função que analise algum código esotérico bem comentado e analise os comentários, retornando apenas o código. Usando alguns exemplos do desafio anterior, eis a aparência do código bem comentado:

a                #Explanation of what 'a' does
 bc              #Bc
   d             #d
    e            #Explanation of e
     fgh         #foobar
        ij       #hello world
          k      #etc.
           l     #so on
            mn   #and
              op #so forth

Aqui está o que você precisa fazer para extrair o código. Primeiro, remova o caractere de comentário ( #), o espaço antes dele e tudo depois do caractere de comentário.

a               
 bc             
   d            
    e           
     fgh        
        ij      
          k     
           l    
            mn  
              op

Em seguida, recolha cada linha para cima em uma única linha. Por exemplo, como bestá na segunda coluna da linha dois, quando a recolhermos, ela estará na segunda coluna da linha um . Similarmente,c será colocado na terceira coluna da linha um e dna quarta. Repita isso para cada personagem e você obtém o seguinte:

abcdefghijklmnop

Nota importante: parece que a solução trivial é apenas remover os comentários, remover todos os espaços e juntar todas as linhas. Esta não é uma abordagem válida! Como o código original pode ter espaços, eles serão removidos com essa abordagem. Por exemplo, esta é uma entrada perfeitamente válida:

hello         #Line one
              #Line two
       world! #Line three

E a saída correspondente deve ser:

hello  world!

O desafio:

Escreva um programa ou função que receba o código comentado como entrada e emita ou retorne o código com todos os comentários analisados. Você deve produzir o código sem espaços à direita, embora uma nova linha à direita seja permitida. O caractere de comentário sempre será #e sempre haverá um espaço extra antes do início dos comentários. #irá não aparecem na seção de comentários da entrada. Para manter o desafio mais simples, eis algumas entradas que você não precisa lidar com:

  • Você pode assumir que o código não terá dois caracteres na mesma coluna. Por exemplo, esta é uma entrada que viola esta regra:

    a  #A character in column one
    bc #Characters in columns one and two
    
  • Você também pode supor que todos os caracteres de comentário apareçam na mesma coluna. Por exemplo, esta entrada:

    short       #this is a short line
          long        #This is a long line
    

    viola essa regra. Isso também significa que# não estará na seção de código.

  • E, por último, você não precisa lidar com seções de código com espaços à esquerda ou à direita. Por exemplo,

      Hello,          #
             World!   #
    

Você também pode assumir que a entrada contém apenas caracteres ASCII imprimíveis.

Exemplos:

Input:
hello         #Line one
              #Line two
       world! #Line three

Output:
hello  world!

Input:
E                                                   #This comment intentionally left blank
 ac                                                 #
   h s                                              #
      ecti                                          #
          on is                                     #
                one c                               #
                     haracte                        #
                            r longer                #
                                     than the       #
                                              last! #

Output:
Each section is one character longer than the last!

Input:
4          #This number is 7
 8         #
  15       #That last comment is wrong.
    16     #
      23   #
        42 #

Output:
4815162342

Input:
Hello                     #Comment 1
      world               #Comment 2
           ,              #Comment 3
             how          #Comment 4
                 are      #Comment 5
                     you? #Comment 6

Output:
Hello world, how are you?

Input:
Prepare                               #
        for...                        #
                        extra spaces! #

Output:
Prepare for...          extra spaces!

Você pode digitar qualquer formato razoável que desejar, por exemplo, uma lista de strings, uma única string com novas linhas, uma lista 2D de caracteres, etc. A resposta mais curta em bytes vence!

DJMcMayhem
fonte
Precisamos aceitar código com caracteres menores que o próximo?
Wizzwizz4 13/09/16
Você poderia adicionar o caso de teste com a linha vazia com apenas dois espaços (como o hello world!que você mostrou)? Além disso, você declara: " #não aparecerá na seção de comentários da entrada. ", Mas pode ocorrer no próprio trecho de código?
Kevin Cruijssen 13/09/16
@KevinCruijssen Veja minhas edições
DJMcMayhem
@ wizzwizz4 Eu não tenho certeza se eu entendi sua pergunta
DJMcMayhem
@DJMcMayhem Exemplo: do {stuff} while (condition);com a explicação em ordem do while (condition); #Explainythingentão {stuff} #Explainything.
Wizzwizz4 13/09/16

Respostas:

18

Geléia , 8 7 bytes

»/ṣ”#ḢṖ

Experimente online!

Como funciona

»/ṣ”#ḢṖ  Main link. Argument: A (array of strings)

»/       Reduce the columns of A by maximum.
         Since the space is the lowest printable ASCII characters, this returns the
         non-space character (if any) of each column.
  ṣ”#    Split the result at occurrences of '#'.
     Ḣ   Head; extract the first chunk, i.e., everything before the (first) '#'.
      Ṗ  Pop; remove the trailing space.
Dennis
fonte
2
Isso é apenas ... uau.
Jonathan Allan
3
Estou tão gelatinosa agora.
precisa saber é o seguinte
Como você consegue invadir isso no seu telefone?
simbabque 13/09/16
2
@simbabque Paciência e muita colagem de cópias.
Dennis
Eu estou sempre colocando usando um 9-ferro, talvez seja a hora que eu aprendi a usar um taco quando no green ...
Magia Octopus Urna
13

Python 2, 48 43 bytes

lambda x:`map(max,*x)`[2::5].split(' #')[0]

Graças a @xnor por jogar fora 5 bytes!

Test it on Ideone.

Dennis
fonte
1
I think you can just do map(max,*x) because max takes any number of arguments and None is small.
xnor
Right, I always forget that map can be used like that... Thanks!
Dennis
1
How does the `...`[2::5] trick work?
smls
1
@smls `...` is equivalent to repr(...), so for the list of singleton strings ['a', 'b', 'c'], you get the string "['a', 'b', 'c']". Finally, [2::5] chops off the first two characters ("['") and takes every fifth character of the remaining string.
Dennis
5

JavaScript (ES6), 97 75 60 bytes

Thanks to @Neil for helping golf off 22 bytes

a=>a.reduce((p,c)=>p.replace(/ /g,(m,o)=>c[o])).split` #`[0]

Input is an array of lines.

  • a is array input
  • p is previous item
  • c is current item
  • m is match string
  • o is offset
ASCII-only
fonte
I count 96 bytes? Also, the m regexp flag is unnecessary (did you have a $ at one point?) as is the space in (p, c). Finally, I think replace will work out shorter than [...p].map().join.
Neil
97 for me, both from manual length and userscript, maybe you didn't count the newline, but only because I accidentally included the semicolon
ASCII-only
I see now - I hadn't copied the ; which isn't required (JavaScript has ASI).
Neil
Yeah, sorry, I had it to make sure Chromium console puts the function call outside the function body (had it once on a badly written lambda)
ASCII-only
Oh wow, I didn't realise replace would help so much, that's really neat!
Neil
4

Perl, 35 34 32 bytes

Includes +1 for -p

Give input on STDIN

eso.pl

#!/usr/bin/perl -p
y/ /\0/;/.#/;$\|=$`}{$\=~y;\0; 

Notice that there is a space after the final ;. The code works as shown, but replace \0 by the literal character to get the claimed score.

Ton Hospel
fonte
Very nice code. That $a|=... is rather well done, it took me a while to figure out what you were doing! One question though : *_=a seems to be roughly equivalent to $_=$a, why is that?
Dada
*_=a is a very obscure glob assignment which aliases the _ globals and the a globals. So it's not so much a copy from $a to $_ but from that point on (global) $a and $_ are actually the same variable. All to save 1 byte...
Ton Hospel
Ok, thanks for the explanation! (and nice improvement thanks to `$\`)
Dada
3

Python 2, 187 bytes

def f(x,o=""):
 l=[i[:i.index("#")-1]for i in x]
 for n in range(len(l[0])):
  c=[x[n]for x in l]
  if sum([1for x in c if x!=" "])<1:o+=" "
  else:o+=[x for x in c if x!=" "][0]
 print o

I'm gonna golf this more tomorrow I have school ;)

Daniel
fonte
1 for can be reduced to 1for. Also, if the sum of the list (at line 5) can't be negative, you can just check for <1 instead of ==0. Happy school day! :D +1.
Yytsi
2

Ruby, 63 bytes

Basically a port of Dennis' Jelly answer. Takes input as an array of strings.

->a{l,=a
l.gsub(/./){a.map{|m|m[$`.size]||$/}.max}[/(.+) #/,1]}

See it on eval.in: https://eval.in/640757

Jordan
fonte
2

CJam, 12 bytes

Thanks to Sp3000 for saving 2 bytes.

{:.e>_'##(<}

An unnamed block that takes a list of strings (one for each line) and replaces it with a single string.

Try it online!

Explanation

:.e>  e# Reduce the list of strings by elementwise maximum. This keeps non-spaces in
      e# favour of spaces. It'll also wreak havoc with the comments, but we'll discard
      e# those anyway.
_'##  e# Duplicate and find the index of '#'.
(<    e# Decrement that index and truncate the string to this length.
Martin Ender
fonte
2

J, 30 bytes

(#~[:<./\'#'~:])@(>./&.(3&u:))

Takes a list of strings as input. Basically uses the same approach as Dennis in his Jelly answer.

Commented and explained

ord =: 3 & u:
under =: &.
max =: >./
over =: @
maxes =: max under ord
neq =: ~:
arg =: ]
runningMin =: <./\
magic =: #~ [: runningMin ('#' neq arg)

f =: magic over maxes

Intermediate steps:

   p
Hello                     #Comment 1
      world               #Comment 2
           ,              #Comment 3
             how          #Comment 4
                 are      #Comment 5
                     you? #Comment 6
   maxes p
Hello world, how are you? #Comment 6
   magic
#~ ([: runningMin '#' neq arg)
   3 neq 4
1
   '#' neq '~'
1
   '#' neq '#'
0
   '#' neq maxes p
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1
   runningMin 5 4 2 5 9 0 _3 4 _10
5 4 2 2 2 0 _3 _3 _10
   runningMin '#' neq maxes p
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
   0 1 0 1 1 0 # 'abcdef'
bde
   'abcdef' #~ 0 1 0 1 1 0
bde
   (maxes p) #~ runningMin '#' neq maxes p
Hello world, how are you? 
   (#~ [: runningMin '#' neq arg) maxes p
Hello world, how are you? 
   ((#~ [: runningMin '#' neq arg) over maxes) p
Hello world, how are you? 
   (magic over maxes) p
Hello world, how are you? 

Test case

   f =: (#~[:<./\'#'~:])@(>./&.(3&u:))
   a
Hello                     #Comment 1
      world               #Comment 2
           ,              #Comment 3
             how          #Comment 4
                 are      #Comment 5
                     you? #Comment 6
   $a
6 36
   f a
Hello world, how are you?
Conor O'Brien
fonte
2

Javascript (ES6), 63 bytes

a=>a.reduce((p,c)=>p+/(.+?)\s+#/.exec(c)[1].slice(p.length),'')

Takes input as an array of strings.

F=a=>a.reduce((p,c)=>p+/(.+?)\s+#/.exec(c)[1].slice(p.length),'')

input.oninput = update;
update();

function update() {
  try {
    output.innerHTML = F(input.value.trim().split`
`);
  } catch(e) {
    output.innerHTML = 'ERROR: INVALID INPUT';
  }
}
textarea {
  width: 100%;
  box-sizing: border-box;
  font-family: monospace;
}
<h2>Input:</h2>
<textarea id="input" rows="8">
a                #Explanation of what 'a' does
 bc              #Bc
   d             #d
    e            #Explanation of e
     fgh         #foobar
        ij       #hello world
          k      #etc.
           l     #so on
            mn   #and
              op #so forth
</textarea>
<hr />
<h2>Output:</h2>
<pre id="output">
</pre>

George Reith
fonte
1

Retina, 32 bytes

Byte count assumes ISO 8859-1 encoding.

Rmr` #.+|(?<=^(?<-1>.)+).+?¶( )+

Try it online!

Martin Ender
fonte
1

Pyke, 15 10 bytes

,FSe)s\#ch

Try it here!

Port of the Jelly answer

,          -     transpose()
 FSe)      -    map(min, ^)
     s     -   sum(^)
      \#c  -  ^.split("#")
         h - ^[0]
Blue
fonte
1

C# 157 122 Bytes

Golfed 35 bytes thanks to @milk -- though I swear I tried that earlier.

Takes input as a 2-d array of characters.

string f(char[][]s){int i=0;foreach(var x in s)for(i=0;x[i]!=35;i++)if(x[i]!=32)s[0][i]=x[i];return new string(s[0],0,i);}

157 bytes:

string g(char[][]s){var o=new char[s[0].Length];foreach(var x in s)for(int i=0;x[i]!=35;i++)if(x[i]!=32|o[i]<1)o[i]=x[i];return new string(o).TrimEnd('\0');}
pinkfloydx33
fonte
Shouldn't Trim() work instead of TrimEnd()? Even better, I think you can save a lot of bytes by using s[0] as the output var and using return new string(s[0],0,i) where i is the index of the last code character. That idea may require two for loops instead of the foreach, I'll think about it more and try to write actual code later today.
milk
Trim() will trim from the start as well, which I believe wouldn't be valid. I also was originally doing the loading into s[0] and I had int i; outside of the loop (to reuse it in the return) which I believe ultimately added bytes
pinkfloydx33
1

Pyth, 11 bytes

PhceCSMCQ\#

A program that takes input of a list of strings on STDIN and prints a string.

Try it online

How it works

PhceCSMCQ\#  Program. Input: Q
       CQ    Transpose Q
     SM      Sort each element of that lexicographically
    C        Transpose that
   e         Yield the last element of that, giving the program ending with ' #' and some
             parts of the comments
  c      \#  Split that on the character '#'
 h           Yield the first element of that, giving the program with a trailing space
P            All but the last element of that, removing the trailing space
             Implicitly print
TheBikingViking
fonte
1

sed, 126 bytes

:a;N;$!ba;s,#[^\n]*\n,#,g;s,^,#,;:;/#[^ ]/{/^# /s,^# *,,;t;H;s,#.,#,g}
t;/#[^ ]/!{H;s,#.,#,g};t;g;s,\n#(.)[^\n]*,\1,g;s,...$,,

Requires a newline at the end of the input.
I'm sure I can golf this a little more, but I'm just happy it works for now.

Riley
fonte
0

Jelly, 27 bytes

żḟ€” ;€” Ḣ€
i€”#’©ḣ@"ç/ḣ®ṪṖ

Test it at TryItOnline

Uses the strictest spec - the extra space before the comment character is removed at the cost of a byte.

Input is a list of strings.

Jonathan Allan
fonte
@Erik the Golfer - maybe so, but did you see the crushing he gave me here?
Jonathan Allan
0

Ruby, 77 bytes

puts File.readlines("stack.txt").join('').gsub(/\s{1}#.*\n/,'').gsub(/\s/,'')
Forwarding
fonte
Hardcoding an input filename is not an acceptable method of input.
Mego
@Mego, where can I find the rules of what's "acceptable"?
Forwarding
0

TSQL, 216 175 bytes

Golfed:

DECLARE @ varchar(max)=
'hello         #Line one
              #Line two
       world! #Line three'

DECLARE @i INT=1,@j INT=0WHILE @i<LEN(@)SELECT @=stuff(@,@j+1,len(x),x),@j=iif(x=char(10),0,@j+1),@i+=1FROM(SELECT ltrim(substring(@,@i,1))x)x PRINT LEFT(@,patindex('%_#%',@))

Ungolfed:

DECLARE @ varchar(max)=
'hello         #Line one
              #Line two
       world! #Line three'

DECLARE @i INT=1,@j INT=0
WHILE @i<LEN(@)
  SELECT @=stuff(@,@j+1,len(x),x),@j=iif(x=char(10),0,@j+1),@i+=1
  FROM(SELECT ltrim(substring(@,@i,1))x)x
PRINT LEFT(@,patindex('%_#%',@))

Fiddle

t-clausen.dk
fonte
0

Javascript, 56 34 bytes, non-competing

q=>q.split(/\n/).map(x=>/ (.?) #./.exec(x)[1]).join()

q=>q.replace(/^ *| *#.*$\n?/gm,'')

As @n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ pointed out, I am not prepared for extra spaces

BlackCap
fonte
Doesn't pass the "Prepare for extra spaces" case
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
0

Dyalog APL, 22 bytes

Inspiration.

(⎕UCS¯2↓⍳∘35↑⊢)⌈⌿∘⎕UCS

(

⎕UCS character representation of

¯2↓ all but the last two of

⍳∘35↑ up until the position of the first 35 ("#"), in that which is outside the parenthesis, taken from

that which is outside the parenthesis

) namely...

⌈⌿ the columnar maximums

of

⎕UCS the Unicode values

TryAPL online!

Adám
fonte
How many bytes?
acrolith