5
\$\begingroup\$

Write the shortest possible code which converts tabs to spaces in the input. Tab size should be supplied as a parameter or be hardcoded in the code in a single place.

Spaces on output should point to the right column, e.g. (\t represents a tab character):

a\tb
aa\tb
aaa\tb
aaaa\tb

should become (for tab size 4):

a   b
aa  b
aaa b
aaaa    b

Of course there can be more than one tab in a line.

Line separator and tab character should match the system defaults (e.g. ASCII 10 and 9 on Unix).

\$\endgroup\$
10
  • 3
    \$\begingroup\$ I think this would be too trivial in any language with RegExp support. And there is also a coreutils utility expand which does just this. \$\endgroup\$
    – zeppelin
    Jan 26, 2017 at 11:48
  • 4
    \$\begingroup\$ Possible duplicate \$\endgroup\$
    – Emigna
    Jan 26, 2017 at 11:51
  • \$\begingroup\$ Related \$\endgroup\$
    – Emigna
    Jan 26, 2017 at 11:53
  • 1
    \$\begingroup\$ I did not notice it was already there, is there a way to delete a question? \$\endgroup\$
    – mik
    Jan 26, 2017 at 11:55
  • 2
    \$\begingroup\$ In the future, please post your challenges in the Sandbox and let it sit there for a couple of days. \$\endgroup\$
    – steenbergh
    Jan 26, 2017 at 11:57

8 Answers 8

2
\$\begingroup\$

Perl 5, 36 bytes

1while s/	/$"x($^I-length($`)%$^I)/e

Try it online!

Tab length is controlled with -i command-line parameter.

\$\endgroup\$
2
\$\begingroup\$

Python 2, 106 bytes

def f(s,w):
 for l in s.split('\n'):
  L=''
  for x in l.split('\t'):L+=' '*(w-(len(L)%w))+x
  print L[w:]

Try it online!

\$\endgroup\$
0
1
\$\begingroup\$

Vim, 16 bytes

:se ts=4 et
:ret
\$\endgroup\$
2
  • 2
    \$\begingroup\$ you can combine setting the two options on a single line and shorten :set to :se \$\endgroup\$
    – ngn
    Jun 18, 2018 at 16:42
  • \$\begingroup\$ I would expect the settings unchanged at the end. \$\endgroup\$
    – mik
    Mar 17, 2021 at 9:32
1
\$\begingroup\$

Pyth, 24 bytes

VQ=+k:NJ"   "d=.[kd|nNJ4)k

Try it here

Explanation

VQ=+k:NJ"   "d=.[kd|nNJ4)k
VQ                      )    For each character in the input...
  =+k:NJ"   "d               ... add the character with tab replaced by space
                             to k (initially empty)...
              =.[kd          ... then pad k with spaces...
                   |nNJ4     ... to the nearest multiple of 4 if the character
                             is a tab and 1 otherwise.
                         k   Output k.

Alternatively, if we want to input the tab length, we can do so with Vz=+k:NJ" "d=.[kd|nNJQ)k.
Try it here.

\$\endgroup\$
0
\$\begingroup\$

Java 11, 134 bytes

n->s->{for(var l:s.split("\n")){var t="";for(var p:l.split("\t"))t+=" ".repeat(n-t.length()%n)+p;System.out.println(t.substring(n));}}

This time an answer for which I correctly read the challenge.. >.>

Try it online.
NOTE: Because Java 11 isn't on TIO yet, the String.repeat(int) has been emulated with repeat(String,int) for the same byte-count.

Explanation:

n->s->{                      // Method with int & String parameters and String return-type
  for(var l:s.split("\n")){  //  Split the input by newlines, and loop over the lines:
    var t="";                //   Temp-String, starting empty
    for(var p:l.split("\t")) //   Split the line by tabs, and loop over the parts
      t+=" ".repeat(n-t.length()%n)
                             //    Append `n - length_of_t modulo-n` amount of spaces,
         +p;                 //    as well as part `p` to the temp-String
      System.out.println(    //    Print with trailing new-line:
        t                    //     The temp-String `t`
         .substring(n));}}   //      after we've removed the trailing spaces
\$\endgroup\$
0
\$\begingroup\$

Excel VBA, 118

An anonymous VBE immediate window function that takes an input string from range [A1] and an input tab length from range [B1], and outputs to the console.

For Each l In Split([A1],vbLf):Do:i=InStr(1,l,"\t"):l=Replace(l,"\t",Space([B1]-(i-1)Mod[B1]),,1):Loop While i:?l:Next

Ungolfed

Public Sub tabReplace(ByRef value As String, Optional tabLen As Integer = 4)
    Dim line, index As Integer
    For Each line In Split(value, vbLf)
        Do
            Let index = InStr(1, line, "\t")
            Let line = Replace(line, "\t", Space(tabLen - (index - 1) Mod tabLen), , 1)
        Loop While index
        Debug.Print line
    Next
End Sub
\$\endgroup\$
0
\$\begingroup\$

Python 2, 103 bytes

def F(I,c):
 while'\t'in I:t=I.find('\t');I=I.replace('\t',' '*(c-(t+~I[:t].rfind('\n'))%c),1)
 print I

Try it online!

I wanted to evade split and use some replace (tbh I've started with regex).

I replace each \t with c-(t+~I[:t].rfind('\n'))%c number of spaces. Where t - index of current \t and t+~I[:t].rfind('\n') is distance to the closest \n (or start of string) on left.

\$\endgroup\$
0
\$\begingroup\$

Wolfram Language (Mathematica), 40 bytes

StringReplace[#,"	"->Array[" "&,4]<>""]&

Try it online!

Sadly, Mathematica doesn't let you multiply a string by a number to duplicate it, otherwise it would be shorter than Perl.


Explanation:

StringReplace[#, Replace all instances of

" " a tab character

->Array[" " with an array of spaces

,4] four long

<>""]& joined to the empty string.

\$\endgroup\$
3
  • \$\begingroup\$ the answer should preserve columns, and not always add 4 spaces \$\endgroup\$
    – mik
    May 30 at 9:27
  • \$\begingroup\$ I don't understand, sorry. \$\endgroup\$
    – Romanp
    May 31 at 12:59
  • \$\begingroup\$ a tab after a single another character at the beginning of the line should be converted to 3 spaces, not 4; look at the example in the question \$\endgroup\$
    – mik
    Jun 1 at 8:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.