Akhiri tab versus perang antariksa


24

Akhiri tab versus perang antariksa

Jadi, ada banyak perdebatan apakah akan menggunakan tab atau spasi untuk indentasi / memformat kode. Dapatkah Anda membantu universitas menyelesaikan perselisihan, dengan pergi ke metode pemformatan unik yang sangat gila .


Tugas Anda adalah menulis program atau fungsi lengkap yang memperluas semua tab menjadi empat ruang. Dan kemudian mengganti serangkaian n spasi terkemuka dengan "/ (n - dua bintang di sini) /". Anda akan menerima input lebih dari beberapa baris dalam format apa pun (array string tunggal string untuk setiap baris baru. Array kolom dll.)

Masukan sampel dicuri tanpa malu-malu . Perhatikan bahwa sejak tab diperluas secara otomatis ke empat spasi di SE, saya mewakilinya sebagai karakter "^", tetapi Anda juga harus menangani tab (codepoint 0x09). Semua karakter "^" mewakili tabulasi.

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! 

Output sampel

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! 

Karena universitas membutuhkan ruang untuk mengunduh Vim dan Emacs, Anda hanya memiliki sedikit penyimpanan untuk kode Anda. Karenanya ini adalah dan kode terpendek menang. Anda dapat mengasumsikan bahwa input terbentuk dengan baik dan garis dengan kurang dari empat spasi (setelah penggantian tab) dapat mengakibatkan perilaku yang tidak terdefinisi.

Penolakan

Strategi pemformatan "luar biasa" ini berasal dari Geobits, dan direproduksi dengan izinnya. Tidak ada programmer yang terluka selama produksi tantangan ini.


1
Akankah tab hanya muncul di awal baris (yaitu sebagai lekukan)? Bisakah garis memiliki indentasi campuran (tab + spasi)?
Lynn

20
Seseorang tolong kirimkan jawaban yang ditulis di Whitespace .
GuitarPicker

2
Haruskah kita mempertimbangkan garis yang dimulai dengan /*, atau dapatkah itu dianggap bukan "masukan yang dibentuk dengan baik"? File sumber C ++ akan menjadi tes yang lebih baik, karena komentar multiline-nya /* */mungkin akan memecahkan beberapa jawaban yang menggantikan pertama dan terakhir dari spasi utama dengan /, dan kemudian melanjutkan untuk mengisi spasi dengan *.
seshoumara

1
Perang telah berakhir: medium.com/@hoffa/… (Kecuali jika Anda sedang memprogram dalam bahasa C, tampaknya.)
Gelas

1
@RohanJhunjhunwala Jadi sekarang saya mengajukan pertanyaan pertama saya lagi, karena ini bukan tentang kode yang dapat dikompilasi. Bayangkan /* */kode C ++ yang sama , tetapi kali ini di awal baris. Menurut spesifikasi Anda itu harus dibiarkan apa adanya. Di sini jebakannya, dan sudah menemukan jawaban yang salah, bahwa regex seperti say /\** /digunakan untuk mengisi ruang-ruang antara // dengan tanda bintang akan mengubah garis menjadi /***/. Saya telah melihat konversi ini juga /*//*/. Saya menganggap keduanya salah.
seshoumara

Jawaban:


2

V , 21 , 20 byte

Íô/    
Î^hr/hv0r*r/

Cobalah online!

Ini benar-benar hanya port langsung dari jawaban vim saya. Perbedaan yang mencolok:

  • The Íperintah (Global pengganti) secara otomatis mengisi /gbendera, yang menyimpan dua byte

  • ô identik dengan \t

  • ÎAdalah mnemonik untuk :%norm, dan juga mengisi ruang yang diperlukan antara :%normdan set penekanan tombol.

  • Pengembalian trailing carriage di bagian akhir ditambahkan secara implisit.


27

Vim, 37, 34, 33, 32 byte

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

Cobalah online!

Perhatikan bahwa ini membutuhkan trailing carriage return (enter) di vim, meskipun tidak dalam penerjemah online.

Ini menggunakan penerjemah V karena itu kompatibel ke belakang. Solusi yang sangat mudah.

Berikut adalah gif yang memungkinkan Anda melihat solusi terjadi secara real time. Ini menggunakan versi yang sedikit lebih lama, dan saya menambahkan beberapa penekanan tombol untuk membuatnya berjalan lebih lambat sehingga Anda dapat melihat apa yang terjadi:

masukkan deskripsi gambar di sini

Dan inilah penjelasan cara kerjanya:

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

Saya akan memberi +1 untuk digunakan gtetapi kemudian Anda diedit untuk tidak menggunakan g: / +1 tetap: D
Downgoat

@ downgoat Haha, terima kasih! Saya sebenarnya jauh lebih bangga dengan versi tanpa :gkarena menyalahgunakan fitur yang kurang dikenal: normperintah dibatalkan jika ^F<space>gagal. Jadi :%norm ^F<space>foopada dasarnya hal yang sama seperti :g/^ /norm fooperetasan Vim yang menyenangkan. : D
DJMcMayhem

ya, saya pikir ^ F digunakan untuk memposisikan layar. apakah ada perilaku yang berbeda di dalam norm?
Downgoat

1
@ downgoat Haha, bukan itu ^F, bukan <C-f>notasi kunci Silly Vim. Dalam hal ini ^, lompat ke karakter non-spasi pertama, dan F<space>Yang menemukan ruang pertama di belakang kursor.
DJMcMayhem

ohhh, itu jauh lebih masuk akal sekarang> _>
Downgoat

11

Perl, 41 byte

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

Jalankan dengan -pbendera, seperti:

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

Ganti dengan tab (dalam Bash, coba ketikkan Control-V Tab.)


1
Cara perlmengganti referensi balik itu di tempat, saya berharap seditu juga.
seshoumara

7

Cheddar , 60 57 56 byte

Disimpan 3 byte berkat @Conor O'Brien

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

Saya berharap Cheddar memiliki format string yang lebih baik.

Cobalah online!

Penjelasan

Ini sebuah fungsi. @adalah properti yang difungsikan (misalnya ruby &:) yang memungkinkan Anda melakukan hal-hal seperti: `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
 )

Jika Anda tidak terbiasa dengan regex:

/^ +/gm

ini pada dasarnya cocok dengan satu atau lebih ( +) spasi ( ) di awal ( ^) dari setiap gbaris ( m).


cara kerja tab literal di cheddar regexes? juga, /^ +/cukup sebagai sebuah regex, karena kita dapat mengasumsikan bahwa ruang terdepan setidaknya akan memiliki panjang 4.
Conor O'Brien

@ ConorO'Brien Saya percaya mereka melakukannya tetapi saya belum menguji
Downgoat

Tab seharusnya diganti sebelum transformasi.
Conor O'Brien

@ ConorO'Brien oh> _> Saya sudah seperti itu awalnya dan kemudian saya mengubahnya
Downgoat

6

Mathematica, 97 byte

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

Fungsi anonim. Mengambil string sebagai input dan mengembalikan string sebagai output.


5

Python 3, 124 byte

Menggunakan regex yang baik.

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

Ide itu!


4

Jawa 210 207 byte

Ini adalah solusi referensi yang mengimplementasikannya secara naif.

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, lalu ada Java pada 210 byte: P mengapa aku tidak terkejut
Downgoat

1
Kode yang sangat ringkas di java: P
Rohan Jhunjhunwala

Anda dapat mengubah terakhir untuk loop untuk menyimpan 1 byte: for(int j=0;++j<i-1;). Anda juga dapat menghapus int sebelumnya j, dan meletakkannya setelah int yang sudah ada:int i=s.length()-(x=s.replaceAll("^\\s+", "")).length(),j;
Kevin Cruijssen

tidak bisakah itu lambda untuk mencukur byte menggunakan (a) -> {...}?
bunyaCloven

Setidaknya masih dapat dibaca dan tidak perlu komentar lebih lanjut: o)
René

3

JavaScript ES6, 75 byte

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

Ganti \tdengan tab literal dalam kode Anda.


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

Mengingat definisi yang sangat longgar dari array string yang diberikan dalam posting awal, saya telah menggunakan Stream<String>yang memungkinkan untuk beberapa penghematan byte akibatnya.

Saya menggunakan teknik yang berbeda dari RI untuk mencapai tujuan yang sama. Algoritme itu sendiri agak sama.

Pengujian dan ungolfed :

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

The \tharus diganti dengan karakter tab yang sebenarnya (0x09).

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

Cobalah online!

Penjelasan

\t
4$* 

Ganti setiap tab dengan empat spasi.

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

Transform setiap baris secara terpisah ( %) dengan mencocokkan 2+Nspasi pada awal baris dan menggantinya dengan /.../mana ...adalah Nsalinan *.



2

SED (56 +1 untuk -r) 57

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

Di mana tab
1. menggantikan tab dengan spasi.
2. menggantikan ruang utama pertama dan terakhir dengan /.
3. mengganti spasi pertama setelah /dan 0+ *dengan *sampai tidak ada kecocokan.


Karena sed ditentukan, tidak ada tanda kutip tunggal yang diperlukan di sekitar kode, sama dengan menghapus -r '' dari jawaban sed Anda yang lain, karena Anda dapat menganggap skrip tersebut disimpan dalam file sumber yang Anda jalankan -f. Setiap flag tambahan yang digunakan seperti n atau r harus dihitung masing-masing satu byte. Jadi di sini, Anda menghemat 2 byte.
seshoumara

Itulah yang saya pikirkan, tetapi saya ingin yakin. Terima kasih.
Riley

Perintah ;setelah t juga tidak perlu. Sedangkan untuk kode itu sendiri, Anda memerlukan ^ di awal sperintah ketiga , jika tidak input seperti ini "3/5" diubah menjadi "3 / * 5". Pada sperintah pertama Anda benar-benar memiliki tab di sana, tetapi itu tidak ditampilkan dengan benar dan menyesatkan, jadi gunakan \ t atau tentukan setelahnya, karakter itu adalah tab.
seshoumara

@seshoumara Terima kasih, saya mencoba memposting dari ponsel saya ... Ini bukan hal termudah untuk dilakukan.
Riley

Saya pikir saya telah menghabiskan lebih banyak waktu mengedit jawaban ini daripada yang lainnya digabungkan. Terima kasih untuk bantuannya!
Riley

1

Universitas harus mempertimbangkan untuk memberi sedikit lebih banyak ruang untuk program di Emacs Lisp (atau standar untuk tabify dan untabifysendirian), karena mereka mendapatkan lebih banyak kata daripada Java. Ini juga harus memperhatikan siswa (atau guru) yang ukuran identitasnya lebih kecil dari empat atau yang kebetulan kode dalam beberapa bahasa seperti-C.

Solusi berikut ini memiliki 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)))))))))

Dengan asumsi bahwa tab-widthtidak perlu diatur secara eksplisit, kita dapat menyimpan 20 dari mereka.

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

Dan versi yang tidak serigala akan terlihat seperti ini

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

Kami pertama untabify- tama wilayah sebelum melompat ke awal. Kemudian, ketika kita melihat spasi putih di awal baris, kita menggantinya dengan komentar sepanjang kata spasi putih. Tepatnya, komentar yang akan dimasukkan dibangun oleh

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

yang dengan sendirinya membutuhkan 97 byte. Solusi yang lebih pendek untuk menyalin beberapa string dan n kali sangat dihargai.


1

Rubi, 52 47 + 1 (p flag) = 48 byte

Sunting : disimpan sepanjang 5 byte, berkat Value Ink

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

1
Bisakah Anda menggunakan pflag untuk mengambil keuntungan dari fakta bahwa (g) sub memodifikasi $_dan dengan demikian mengubah nilai cetakan? ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'
Nilai Tinta

Terima kasih, saya tidak tahu (g)subtanpa bang dapat memodifikasi di $_sini.
michau

1

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

Sunting: 1 byte lebih sedikit berkat saran Riley .

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

Jalankan: sed -rf formatter.sed input_file

Alasan untuk memisahkan dengan \nspasi utama dari sisa teks pada baris itu, adalah karena jika tidak, baris C ++ dimulai dengan komentar seperti ini /* */akan diubah menjadi /*****/oleh baris 4 yang lebih disukai s,^(/\**) ,\1*,atau bahkan s,^(/\**) ( */),\1*\2,. Karena sed mengeksekusi skrip untuk setiap baris input, tidak ada \nyang diperkenalkan dalam ruang pola saat membaca.


Anda dapat menyimpan byte dengan tidak memasukkan penutup /sampai Anda mengganti \n. Itu menghemat Anda harus mencocokkannya di baris 4.
Riley

@Riley Tangkapan bagus. Diperbarui kodenya.
seshoumara

Anda dapat menyimpan yang lain dengan mengganti \tdengan karakter tab.
Riley

@Riley Itu benar, tetapi karena tidak akan dicetak sebagai tab di sini, saya ragu. Saya akan mengingat hal ini untuk jawaban sed masa depan dengan jumlah byte yang lebih kompetitif.
seshoumara
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.