Astaga, ini tercakup dalam tab!

26

Pengguna lekukan luar angkasa, satukan ! Kita harus berjuang melawan semua pengguna tab rendahan !

Misi Anda (jika Anda memilih untuk menerimanya) adalah menulis program atau fungsi yang menggunakan dua argumen:

  • Sebuah string: Ini adalah input.
  • Bilangan bulat positif: Ini jumlah ruang per tab.

Anda harus melewati setiap baris string dan mengganti setiap tab yang digunakan untuk indentasi dengan jumlah spasi yang diberikan, dan setiap tab yang tidak digunakan untuk indentasi (misalnya di tengah-tengah garis) dengan satu spasi.

Perhatikan bahwa garis-garis seperti \t \tabcperilaku tidak terdefinisi; mereka dimasukkan oleh pengguna tab jahat untuk menyulitkan program Anda.

Menurut Tabs Must Die Society, program Anda harus sesingkat mungkin untuk menghindari deteksi oleh pengguna tab jahat.

Contoh

\t digunakan untuk mewakili tab di sini.

String input:

a
\t\tb\tc
d

Nomor input:

4

Keluaran:

a
        b c
d

Garis tengah diindentasi oleh 8 spasi, 4 per tab (karena angka yang diberikan adalah 4).

String input:

\ta\t\tb

Nomor input:

4

Keluaran:

    a  b

CATATAN: Ini bukan duplikat dari tantangan ekspansi tab ; itu memerlukan format input yang sangat berbeda dan persyaratan yang sedikit berbeda.

kirbyfan64sos
sumber
1
Ya , selama pertanyaannya tidak secara eksplisit meminta angka desimal (yang tidak).
Martin Ender
2
kemungkinan duplikat tab Perluas (implementasikan perluasan (1))
Ismael Miguel
1
Bisakah kita berasumsi bahwa input hanya berisi ASCII, tab, dan baris baru yang dapat dicetak?
Dennis
2
Uji kasus diusulkan: \ta\t\tb, 4(revisi saya sebelumnya gagal yang satu)
Dennis
2
Kami membutuhkan jawaban di Whitespace.
Kaz Wolfe

Jawaban:

7

CJam, 30 24 23 byte

q{_9=NA=Seasi*' ?@?:N}/

Saya biasanya menolak untuk mengirim kode berbahaya di internet ...

Ini adalah program lengkap yang membaca string dari STDIN dan angka sebagai argumen baris perintah.

Cobalah online di juru bahasa CJam .

Bagaimana itu bekerja

q                        Read all input from STDIN.
 {                   }/  For each character C in the input:
  _9=                      Push 1 if C is a tab and 0 otherwise.
     NA=                   See below.
        Seasi*             Push a string of W spaces, where W is the integer from
                           the command-line arguments.
              '            Push a spaces character.
                ?          Select the string if NA= pushed a truthy value, the
                           single space otherwise.
                 @         Rotate C on top of the stack.
                  ?        Select the string of spaces or the single space if _9=
                           pushed 1, the character C otherwise.
                   :N      Save the result in N.

Apa yang NA=dilakukan:

  • Untuk karakter pertama, Nakan berisi nilai default-nya, yaitu string "\n".

    Untuk semua karakter selanjutnya, Nakan berisi hasil iterasi terakhir, yaitu karakter terakhir dari input, karakter spasi atau string dari satu atau lebih spasi.

  • Jika Nadalah string, NA=pilih elemen pada indeks 10 dari N (membungkus). Hasilnya adalah spasi atau karakter linefeed. Keduanya benar.

    Jika N adalah karakter, NA=tekan 1 untuk umpan baris dan 0 sebaliknya.

  • Karena hal di atas, NA=akan mendorong nilai kebenaran untuk karakter pertama, karakter yang didahului oleh linefeed atau karakter yang didahului oleh string spasi (lekukan yang sudah diganti).

    Dalam semua kasus lain (termasuk tabulator yang telah diganti oleh karakter spasi ), NA=akan mendorong nilai falsy.

Dennis
sumber
6
Untung Anda melakukan layanan Internet dengan menghapus tab berbahaya. ;)
Alex A.
19

K5, 53 45 byte

{{,/(b+a&~b:x*&\a:9=y){$[x;x#" ";y]}'y}[x]'y}

Beraksi:

  {{,/(b+a&~b:x*&\a:9=y){$[x;x#" ";y]}'y}[x]'y}[4;(,"a";"\t\tb\tc";,"d")]
(,"a"
 "        b c"
 ,"d")

Saya hanya ingin catatan menunjukkan bahwa pertanyaan ini secara moral tercela.

JohnE
sumber
11
-21346106841 untuk... this question is morally reprehensible.
TheNumberOne
3
Ini harus berakhir di jawaban terpilih teratas, supaya orang akan melihat catatan kaki.
Geobits
Anda dapat mengembalikan hasilnya alih-alih mencetaknya selama 3 byte.
kirbyfan64sos
1
@ kirbyfan64sos: Saya mencetak hasilnya untuk menghindari keharusan untuk bergabung. Jika saya dapat menerima dan mengembalikan hasilnya sebagai daftar string, satu untuk setiap baris, saya bisa menyimpan `0:dan `" \ n "\`.
JohnE
@ JohnE Aku tidak menetapkan aturan yang mengatakan kamu tidak bisa, jadi kurasa kamu bisa. :)
kirbyfan64sos
8

Perl, 23 byte

22 byte kode + 1 byte baris perintah

Semoga tidak terlalu nakal untuk menganggap input numerik dapat diberikan melalui parameter -i! Pastikan untuk mengganti \ t dalam kode di bawah ini dengan karakter tab yang sebenarnya.

s/\G\t/$"x$^I/ge;y/\t/ /

Contoh penggunaan:

printf "a\n\t\tb\tc\nd" | perl -p entry.pl -i4

Atau untuk kenyamanan:

printf "a\n\t\tb\tc\nd" | perl -pe 's/\G\t/$"x$^I/ge;y/\t/ /' -i4

Penjelasan:

Menggunakan -pargumen akan menjalankan program untuk setiap baris dalam input, lalu mencetak hasilnya di akhir.

Dalam contoh di atas, substitusi pengganti diganti \G\tdengan " "x4(spasi diulang empat kali). \Gadalah konstruksi regex yang kurang dikenal yang cocok dengan posisi pertandingan pertama jika iterasi pertama, atau dari posisi pertandingan sebelumnya jika bukan iterasi pertama, artinya hanya akan mengganti semua tab pada awal string, dan akan lakukan satu per satu. The y/\t/ /hanya menggantikan semua tab yang tersisa dengan spasi.

Jarmex
sumber
2

Julia, 69 59 byte

f(s,n)=(r=replace)(r(s,r"^\t*"m,i->" "^endof(i)n),"\t"," ")

Tidak Disatukan:

function f(s::String, n::Int)
    # Replace the leading indentation tabs
    r1 = replace(s, r"^\t*"m, i -> " "^endof(i)n)

    # Replace any remaining tabs between words
    r2 = replace(r1, r"\t", " ")

    # Return
    r2
end

Menyimpan 10 byte dan memperbaiki masalah berkat Glen O!

Alex A.
sumber
Apakah ada manfaatnya untuk mengganti tab indentasi terkemuka secara terpisah? Sepertinya saya harus ditangani langsung oleh bagian "tab yang tersisa". Selain itu, bagian "ganti tab di antara teks" hanya akan cocok dengan satu tab, bagaimana jika Anda memilikinya "hello\t\t1"?
Glen O
Jika kami menganggap semua lekukan dilakukan dengan tab (tidak ada "\t \t"situasi), Anda bisa melakukan ini f(s,n)=(r=replace)(r(s,r"^\t*"m,i->" "^endof(i)n),"\t"," "):, yang menggunakan fungsi pengganti dan akan menangkap semua tab lekukan dalam satu pukulan.
Glen O
@ GlenO Wow, itu benar-benar jenius. Terima kasih banyak!
Alex A.
Saya perhatikan jawaban saya diturunkan. Adakah yang saya lakukan salah? Saya akan dengan senang hati mengatasi masalah apa pun.
Alex A.
Saya tidak melihat masalah apa pun. Mungkin itu hanya salah satu dari tipe pendendam yang downvote karena mereka tidak suka bahasa, atau hal-hal seperti itu? Saya tidak bisa melihat kekurangan.
Glen O
2

Haskell, 82 byte

n!('\t':x)=([1..n]>>" ")++n!x
n!x=f<$>x
f '\t'=' '
f x=x
g n=unlines.map(n!).lines

Lalu g 3 "a\n\t\tb\tc\nd"lakukan hal itu.

Lynn
sumber
2

Mathematica, 42 37 byte

Terima kasih kepada @ LegionMammal978 untuk beberapa saran penghematan kode. Parameter pertama, #adalah untuk teks input, parameter kedua #2,, untuk jumlah spasi per tab.

StringReplace[#,"\t"->" "~Table~{#2}]&
DavidC
sumber
Anda juga dapat mengubah Table[" ",{#2}]ke " "~Table~{#2}untuk menyimpan satu byte. Mengapa Anda StringJoinmemasukkan string kosong ke dalamnya?
LegionMammal978
1

Ruby 49 byte

def r s,t;s.gsub! /^\t/,' '*t;s.gsub!"\t",' ';end
MegaTom
sumber
2
Ini tidak berfungsi jika ada dua tab di awal baris.
Bukan karena Charles
1

JavaScript (ES6), 70

Menggunakan string template, baris baru itu signifikan dan dihitung

(s,n,r=n)=>[...s].map(c=>c<`
`?` `.repeat(r):(r=c<` `?n:1,c)).join``

Tes menjalankan cuplikan di bawah ini di Firefox.

F=(s,n,r=n)=>[...s].map(c=>c<`
`?` `.repeat(r):(r=c<` `?n:1,c)).join``

// TEST
out=x=>O.innerHTML+=x+'\n\n'

out('Input: "A\\n\\t\\tB\\tC\\nD" 4\nOutput:\n'+F('A\n\t\tB\tC\nD',4))

out('Input: "\\tA\\t\\tB" 4\nOutput:\n'+F('\tA\t\tB', 4))
<pre id=O></pre>

edc65
sumber
1
Wow, satu downvote! Bisa jadi seseorang yang tidak bisa membaca atau mengerti 'Uji di Firefox'?
edc65
Saya menduga bias bahasa. Julia dan CJam juga mendapat downvotes.
Dennis
1

CoffeeScript, 72 byte

(s,n)->s.replace(/^\t+/mg,(m)->" ".repeat(m.length*n)).replace /\t/g," "

(Mencoba untuk bermain golf setidaknya 2 gigitan lagi, jadi itu akan mengalahkan solusi ES6 ... Bantuan dihargai: D)

Pemakaian:

f=(s,n)->s.replace(/^\t+/mg,(m)->" ".repeat(m.length*n)).replace /\t/g," "
str="""
My nice\tString
\tIndent <--
\t\tDouble
""" #\t is recognized as tab by CS
alert(f(str,4))
Bojidar Marinov
sumber
1

Retina, 42 byte

Semua kemunculan .adalah spasi, semua \tadalah tab literal (1 byte), dan<empty> merupakan file kosong. Itu hanya untuk keterbacaan. Saya juga tidak sepenuhnya yakin bahwa saya melakukan loop dengan benar, tetapi saya rasa begitu. Setiap baris harus ditempatkan di file sendiri. Saya telah menambahkan 1 byte untuk setiap file tambahan.

Input diasumsikan berada di Unary pada jalurnya sendiri di akhir input.

(1*)$
_$1
m+`(?<!^|\t)\t
.
(`1$
<empty>
)`\t
\t.
\t|_
<empty>

Penjelasan

Saya menambahkan _sebelum masukan Unary untuk membatasi itu selama penggantian, sehingga saya tidak menghapus yang tertinggal dari string input. Lalu, saya mengganti semua tab tidak di awal baris dengan satu spasi. Lalu, saya loop, menghapus satu 1dan menambahkan satu spasi setelah setiap tab, sampai saya kehabisan input. Akhirnya, saya membersihkan dengan menghapus tab dan garis bawah.

mbomb007
sumber
1

Python, 72 68 byte

Tab adalah tab literal (1 byte), jadi r'...'tidak diperlukan. Sayangnya, Python membutuhkan "fixed-width" look-behinds / look-aheads, jadi saya tidak bisa menggunakan (?<!^|\t). Menggunakan metode yang hampir sama dengan solusi Retina saya.

import re
lambda s,n:re.sub('\t',' '*n,re.sub('(?<!^)(?<!\t)\t',' ',s))
mbomb007
sumber
1

Stax , 20 byte

ÜR╧█╧╫≡eX,)~σOÜ¢G╩N‼

Jalankan dan debug itu

Program ini membaca baris pertama sebagai lebar indent, dan sisanya dari input sebagai program.

rekursif
sumber
1

Japt v2.0a0, 17 byte

r/^\t+/m_çVçÃr\tS

Cobalah

Shaggy
sumber
0

Haskell , 75 byte

s#m|let('\t':r)#n=(' '<$[1..n])++r#n;(x:r)#n=x:r#(m^sum[1|x<' ']);e#_=e=s#m

Cobalah online! Ini mengasumsikan input hanya berisi karakter yang dapat dicetak serta tab dan baris baru, sebagaimana diizinkan oleh OP dalam komentar.

Penjelasan:

Fungsi luar #mengambil string sdan angka mdan memanggil #fungsi yang didefinisikan secara lokal dengan argumen yang sama. Ini dilakukan untuk melacak nilai asli m, karena #fungsi bagian dalam mengubah angka:

  • ('\t':r)#n=(' '<$[1..n])++r#nJika Anda menemukan tab, gantilah dengan nspasi dan biarkan ntidak berubah.
  • (x:r)#n=x:r#(m^sum[1|x<' '])Jika beberapa xyang bukan tab ditemui, pertahankan sebagaimana adanya tetapi tetapkan nke nomor asli mjika xmerupakan baris baru dan 1sebaliknya. Hal ini dilakukan oleh m^sum[1|x<' ']: mdibawa ke kekuatan sum[1|x<' ']yang mengevaluasi 1kapan xlebih kecil dari spasi (yaitu baris baru), jadi kita dapatkan m^1 = m. Kalau tidak, itu yang 0kita miliki m^0 = 1.
Laikoni
sumber
0

Java 11, 134 byte

n->s->{var r="";for(var p:s.split("\n")){for(;p.charAt(0)==9;p=p.substring(1))r+=" ".repeat(n);r+=p+"\n";}return r.replace('\t',' ');}

Cobalah online.
CATATAN: Java 11 belum pada TIO, jadi " ".repeat(n)telah ditiru sebagai repeat(" ",n)gantinya (dengan jumlah byte yang sama).

Penjelasan:

n->s->{                 // Method with integer & String parameters and String return-type
  var r="";             //  Result-String, starting empty
  for(var p:s.split("\n")){
                        //  Loop over the rows (split by new-lines)
    for(;p.charAt(0)==9;//   Inner loop as long as the current row starts with a tab
       p=p.substring(1))//     After every iteration: remove the first character (tab)
      r+=" ".repeat(n); //    Append `n` amount of spaces to the result-String
    r+=p+"\n";}         //   Append the rest of the row with a newline to the result
  return r.replace('\t',' ');} 
                        //   Replace any remaining tabs with a space, and return the result
Kevin Cruijssen
sumber