Konversi kawat gigi ke Penjepit Tangan Kanan (Sad Brace)


26

Penjepit tangan kanan adalah gaya bracketing kode di mana kurung kurawal dan titik koma semuanya disejajarkan dengan satu titik di sisi kanan file.

Contoh Gambar buka di sini

Secara umum, ini dianggap praktik buruk, karena beberapa alasan.

Tantangan

Ambil string multiline melalui metode apa pun, dan ubah gaya brace-nya menjadi Right Hand Brace.

Untuk tantangan ini, Anda hanya perlu bekerja pada kode Java, namun, secara teoritis harus bekerja pada kode apa pun yang menggunakan Kawat Gigi dan Titik Koma.

Anda harus mengambil semua {};karakter dalam satu baris, dengan jumlah spasi putih di antara mereka. MISALNYA. }},, ; } }\n\t\t}dan sejajarkan mereka di sisi kanan file melalui penggunaan spasi putih.

sebagai contoh:

a {
b;
{c

harus menjadi

a {
b ;{
c

Atau, secara lebih abstrak, dorong setiap dan semua spasi putih dari kiri semua {};karakter, ke kanan.

Lekukan garis harus tetap dipertahankan. Baris hanya berisi spasi putih setelah perpindahan {};karakter dapat secara opsional dihapus.

Sebagai contoh:

a{
    b{
        c;
    }
}
d;

Mungkin menjadi salah satu

a        {
    b    {
        c;}}
d        ;

atau

a        {
    b    {
        c;}}


d        ;

Didorong ke kanan mengacu pada semua {};karakter yang disejajarkan ke titik yang tidak lebih pendek dari garis terpanjang. Jumlah ruang setelah itu dapat diterima.

Jadi semua di bawah ini dapat diterima:

a {
bc;

a  {
bc ;

a   {
bc  ;

dll ...

Baris dalam kode apa pun dapat berisi {};karakter di antara karakter non-spasi lain, penanganan kasus ini tidak diperlukan, meskipun jika Anda cenderung, Anda harus membiarkannya di tempat. Garis juga mungkin tidak mengandung {};karakter sama sekali, dan ini harus ditangani dengan benar. Seperti yang ditunjukkan di bawah ini.

a {
b ;
c
d }

Karena kami tidak ingin Peninjauan Kode melihat hal-hal mengerikan yang kami lakukan, Anda harus membuat kode Anda sekecil mungkin.

Contoh / Testcases

Java Generik

public class HelloWorld{
       public static void main(String[] args){
           System.out.println("Hello, World!");
       }
}

menjadi...

public class HelloWorld                        {
    public static void main(String[] args)     {
        System.out.println("Hello, World!")    ;}}

Gambar itu sendiri

public class Permuter{
    private static void permute(int n, char[] a){
        if (n == 0){
            System.out.println(String.valueOf(a));
        }else{
            for (int i=0; i<= n; i++){
                permute(n-1, a);
                swap(a, n % 2 == 0 ? i : 0, n);
            }
        }
    }
    private static void swap(char[] a, int i, int j){
        char saved = a[i];
        a[i] = a[j];
        a[j] = saved;
    }
}

menjadi...

public class Permuter                                {
    private static void permute(int n, char[] a)     {
        if (n == 0)                                  {
            System.out.println(String.valueOf(a))    ;}
        else                                         {
            for (int i=0; i<= n; i++)                {
                permute(n-1, a)                      ;
                swap(a, n % 2 == 0 ? i : 0, n)       ;}}}
    private static void swap(char[] a, int i, int j) {
        char saved = a[i]                            ;
        a[i] = a[j]                                  ;
        a[j] = saved                                 ;}}

Python Generik Tidak Sempurna

Untuk kontras

def Main():
    print("Hello, World!");

Main();

menjadi...

def Main():
    print("Hello, World!")    ;
Main()                        ;

Catatan

  • Berlaku celah standar
  • IO standar berlaku
  • Ini adalah , sehingga program terpendek dalam byte menang!
  • Saya tidak bertanggung jawab atas kerusakan yang berkaitan dengan pemrograman dengan gaya Right Hand Brace
  • Selamat bersenang-senang!

Edit Catatan

Saya menulis ulang rincian tantangan, Semoga saya tidak melanggar pandangan siapa pun tentang aturan, saya yakinkan Anda itu tidak disengaja. Ini harus menjadi spesifikasi yang jauh lebih jelas dan tidak saling bertentangan.


Apa vonis pada garis dengan banyak titik koma? Sesuatu sepertiint a=0;System.out.println(a);
Value Ink

2
Itu mungkin bukan gambar terbaik untuk tantangan jika kita tidak perlu menangani loop seperti pada gambar sampel?
Dennis

1
Sepertinya gambar dalam pertanyaan berasal dari contoh ini , yang diikuti oleh tindak lanjut ini , yang memiliki contoh yang lebih kompleks
Ray Toal

2
Bisa dibuat lebih jelas bahwa Anda ingin ;{}karakter dikumpulkan jika mereka berada di baris yang berbeda (itu hanya jelas dari contoh, bukan aturan, dan pada kenyataannya jika garis terdiri dari \t}menjaga lekukan akan berarti tidak bergerak }hingga akhir dari baris sebelumnya)
Chris H

2
Ya Tuhan, tolong katakan padaku tidak ada yang benar-benar melakukan ini dalam praktek untuk bahasa verbal seperti Java ._.
Magic Octopus Mm

Jawaban:


5

V + Bash Utilities, 64 62 61 60 62 byte

1 byte disimpan berkat @DJMcMayhem karena menggabungkan perintah ex

:se ve=all|%!wc -L
y$uò/^ *<93>[{};]
xk$pòò/<84> {};][{};]«$
lDî^R0|p

^Radalah karakter literal untuk <C-r>( 0x12) dan <84>is 0x84dan <94>is 0x94.

wc -Lbekerja pada kebanyakan sistem berbasis * nix, tetapi tidak macOS. Untuk macOS, yang harus Anda lakukan gwc -L setelah mendapatkan coreutils menggunakan brew, jika Anda belum melakukannya.

Cobalah online! (Jawa)

Cobalah online! (Python)

Cobalah online! (Java lagi)

Ini mempertahankan semua garis kosong dan tidak menangani tab, hanya spasi.

Hexdump:

00000000: 3a73 6520 7665 3d61 6c6c 7c25 2177 6320  :se ve=all|%!wc 
00000010: 2d4c 0a79 2475 f22f 5e20 2a93 5b7b 7d3b  -L.y$u./^ *.[{};
00000020: 5d0a 786b 2470 f2f2 2f84 207b 7d3b 5d5b  ].xk$p../. {};][
00000030: 7b7d 3b5d ab24 0a6c 44ee 1230 7c70       {};].$.lD..0|p

Penjelasan

Pertama-tama kita harus bisa memindahkan kursor ke mana saja di buffer, jadi kita gunakan

:se ve=all|...

dan kami rantai ini dengan menggunakan perintah ex lain |

Kita perlu mendapatkan panjang dari garis terpanjang di input. Ini bisa dilakukan dengan perintah shell wc -L.

       ...|%!wc -L

Ini menimpa buffer saat ini (berisi input) dengan hasil wc -L. Ini memberikan output dari sesuatu seperti:

            42

dan kursor mendarat di 4dalam 42. Kemudian kami menyalin nomor ini dengan menggunakany$ : yank teks dari posisi kursor ke akhir baris. Ini dengan mudah menyimpan nomor ini dalam daftar 0. Tetapi lebih lanjut tentang itu nanti. Input diganti dengan nomor ini, jadi untuk kembali, kami tidak melakukannya u.

Sekarang katakan inputnya terlihat seperti ini:

public class HelloWorld{
    public static void main(String[] args){
        System.out.println("Hello, World!");
    }
}

kita perlu memindahkan kawat gigi }dari ujung buffer ke tepat setelahprintln pernyataan.

ò                  " recursively do this until a breaking error:
 /^ *<93>[{};]     "   this compressed regex becomes /^ *\zs[{};]
                   "   this finds any character from `{};` after leading spaces
                   "   the cursor then goes to the `{};`

x                  "   delete character
 k$                "   go to the end of the line above
   p               "   and paste
    ò

Jika regex tidak dapat ditemukan, kesalahan pemecahan terjadi dan keluar dari rekursi yang disebabkan oleh ò.

Sekarang sampai pada bagian utama dari program ini, pindahkan semua kawat gigi dan semi-titik dua dan sejajarkan seperti yang dinyatakan dalam pertanyaan.

ò                  " starts recursion
 /<84> {};][{};]«$ "   compressed form of [^ {};][{};]\+$
                   "   finds a sequence of `{};`s at the end of the line with a non-`{};` char to preceding it
 l                 "   move the cursor 1 to the right (since we were on the non-`{};` char now)
  D                "   delete everything from this position to the end of line
                   "   the deleted text contains `{};`
   î               "   execute as normal commands:
    ^R0            "   contains what's in register `0`, ie the length of the longest line
       |           "   now go to the column specified by that number
        p          "   and paste the contents 
                   " implicit ending `ò`

Sekali lagi, rekursi ini akan dihentikan oleh kesalahan yang disebabkan ketika regex tidak ditemukan di buffer.

Suntingan

  • Digunakan Dsebagai gantid$ (Saya bahkan tidak tahu mengapa saya melewatkan itu di tempat pertama)
  • Terkompresi [^ (dalam regex) ke<84>
  • Memperbaiki bug dengan menggunakan \zs(mengompresi ke dalam <93>) dan dengan menghapus$ in$xk$pò
  • Menghapus baris baru yang tidak berguna
  • Mengubah regex untuk membuat pengajuan kepatuhan dengan aturan baru dan memperoleh 2 byte

Anda dapat menyimpan satu byte jika Anda menggabungkan perintah ex Anda bersama:se ve=all|%!wc -L
DJMcMayhem

@DJMcMayhem Terima kasih, TIL
Kritixi Lithos

4

Ruby, 100 114 108 byte

Membaca nama file sebagai argumen baris perintah. Jika tidak ada nama file yang diberikan, itu akan dibaca dari STDIN. Tidak menangani tab.

Cobalah online!

f=$<.read.gsub(/[\s;{}]*$/){$&.tr"
 ",''}
$><<f.gsub(/(.*?)([;{}]+)$/){$1.ljust(f.lines.map(&:size).max)+$2}



Tidak bekerja dengan ini
Pavel

@Pavel, terima kasih telah memberi tahu saya. Dua masalah yang saya lihat setelah pemipaan ke file adalah A. catchpernyataan lekukan , dan B. tanda koma yang terlalu banyak indentasi, pada baris terpanjang dalam kode. Saya rasa saya tahu hal yang saya butuhkan untuk memperbaikinya, beri saya waktu sebentar. (Juga, saya memperbarui spesifikasi untuk menyebutkan itu tidak dapat menangani tab, dan file Anda memiliki tab.)
Value Ink

Apakah ada tab? Saya baru saja menemukan dan menggantinya, dan itu membuat 0 perubahan.
Pavel

3

Perl , 90 byte

88 byte kode + -p0bendera.

\@a[y///c]for/.*/g;s/(.*?)\K[{};]$/$"x(@a-$1=~y%%%c).$&/gme;1while s/ *
 *([{};]+)$/$1/m

Cobalah online!

Penjelasan singkat:
\@a[y///c]for/.*/g; menghitung panjang garis terpanjang: untuk setiap baris, ia mendefinisikan elemen pada indeks y///c(yaitu ukuran garis) dari array @a. Pada akhirnya, indeks maksimum @a(yaitu ukuran @a) adalah ukuran garis terpanjang.
s/(.*?)\K[{};]$/$"x(@a-$1=~y%%%c).$&/gmemenempatkan {};karakter di akhir baris.
1while s/ *\n *([{};]+)$/$1/mmake membuat kawat gigi pada baris kosong pergi pada baris di atas.

Terima kasih kepada @primo dari siapa saya "mencuri" sebagian kode saya dari sini untuk menghitung panjang garis terpanjang.


Kawat gigi harus kembali ke garis di atas jika hanya ada spasi putih sebelum mereka, jawaban ini tidak melakukan itu
Kritixi Lithos

@KritixiLithos memang, sepertinya baik-baik saja sebelum tantangan ditulis ulang (dari apa yang saya mengerti baik dari tantangan dan komentar). Lagi pula, sudah diperbaiki sekarang (saya sudah punya kode yang ditulis dalam jawaban saya jika Anda tidak memperhatikan).
Dada

1

Python 2: 228 Bytes

import re
g=re.search
def b(a):
    s,l="",a.split('\n')
    r=max([len(k)for k in l]) 
    for k in l:
        n,m=g('[;}{]',k),g('[\w]',k)
        if n:n=n.start()
        if m:m=m.start()
        if n>m and m!=None:s+="\n"+k[:n]+" "*(r-n)
        s+=k[n:]
    print s

Sangat panjang. Saya mungkin harus mulai dari awal ketika saya menyadari bahwa satu-satunya ;{}yang diperlukan pada akhir baris sebelumnya.
Chris H

1

ditumpuk , 133 byte

'\s+([;{}])' '$1'repl lines{!n'[\s;{}]+$'match''join:n\'$'+del\,}"!tr:$size"!$MAXmap@k{e i:e[' 'k i#rpad]"!}map tr[' 'join]map'
'join

Cobalah online! Saya bisa terlalu memikirkan ini ... tapi siapa pun. Saya akan melihatnya lagi besok. Beberapa tips yang bagus:

  1. "! sering dapat digunakan sebagai pengganti map , menyimpan satu atau dua byte, tergantung pada apakah token berikutnya dimulai dengan sebuah kata. Namun, itu hanya dapat digunakan ketika setiap atom dari array ingin dipetakan. Ini mirip dengan peta yang dalam.
  2. Ruang tidak diperlukan setelah fungsi yang dikutip, jadi $MAXmapsama dengan $MAX map, yang pada gilirannya setara dengan [MAX] map. (Memetakan setiap larik ke elemen maksimalnya.)

1

JavaScript (Proposal ES), 139 121 byte

f=
s=>s.replace(/^(.*?)\s*(([;{}]\s*)+)$/gm,(_,t,u)=>t.padEnd(Math.max(...s.split`
`.map(s=>s.length)))+u.replace(/\s/g,``))
<textarea rows=10 cols=40 oninput=o.textContent=f(this.value)></textarea><pre id=o>

Membutuhkan Firefox 48 / Chrome 57 / Opera 44 / Safari 10 / Edge 15 untuk padEnd. Sunting: Disimpan 18 byte berkat @ValueInk.


Apakah Anda benar-benar perlu menjalankan s.replace(r,`$1`)ketika menghitung panjang garis? Jumlah bantalan-kanan yang masuk akal harus cukup, jadi menghitung panjang garis dengan titik koma dan tanda kurung harus baik-baik saja.
Nilai Tinta

0

PHP, 201 194 185 172 167 byte

foreach($f=file(f)as$s)$x=max($x,strlen($a[]=rtrim($s,"{} ;
")));foreach($a as$i=>$c)echo str_pad($c,""<$c|!$i?$x:0),trim(substr($f[$i],strlen($c))),"
"[""==$a[$i+1]];

mengambil input dari file f; mengasumsikan satu baris byte byte dan tidak ada tab; mempertahankan garis kosong.

  • +2 byte untuk membatasi spasi putih: tambahkan +1ke yang keduastr_pad parameter .
  • -6 byte jika dijamin tidak ada baris kode yang terdiri dari satu 0:
    Hapus ""<dan ganti ""==dengan !.

kerusakan

foreach($f=file(f)as$s)             // loop through file
    $x=max($x,strlen(                   // 3. set $x to maximum code length
        $a[]=                           // 2. append to array $a
            rtrim($s,"{} ;\n")          // 1. strip trailing whitespace and braces
    ));
foreach($a as$i=>$c)echo            // loop through $a
    str_pad($c,                         // 1. print code:
        !$i|""<$c                       // if first line or not empty
        ?$x                             // then padded to length $x
        :0                              // else unpadded (= print nothing)
    ),
    trim(substr($f[$i],strlen($c))),    // 2. print braces
    "\n"[""==$a[$i+1]]                  // 3. if next line has code, print newline
;

Anda yakin perlu keluar dari {}kawat gigi di regex?
Kritixi Lithos

@KritixiLithos Mungkin tidak; tapi saya tetap menemukan pendekatan yang lebih pendek.
Titus

0

Java 8, 312 305 byte

s->{String t="([;{}]+)",z[],r="",a;s=s.replaceAll(t+"[\\s\\n]*","$1").replaceAll(t,"$1\n");int m=0,l;for(String q:s.split("\n"))m=m>(l=q.length())?m:l;for(String q:s.split("\n")){z=q.split("((?<="+t+")|(?="+t+"))",2);for(a="",l=0;l++<m-z[0].length();a+=" ");r+=z[0]+a+(z.length>1?z[1]:"")+"\n";}return r;}

Penjelasan:

Coba di sini.

s->{                                  // Method with String parameter and String return-type
  String t="([;{}]+)",                //  Temp regex-String we use multiple times
    z[],a,                            //  Temp String-array and temp String
    r="";                             //  Result-String
  s=s.replaceAll(t+"[\\s\\n]*","$1")  //  We replace all ;{} in the input with zero or more whitespaces/newlines to just ;{}
     .replaceAll(t,"$1\n");           //  and then add a single newline after each group of ;{}
  int m=0,l;                          //  Two temp integers
  for(String q:s.split("\n"))         //  Loop (1) over the lines
    m=m>(l=q.length())?m:l;           //   To determine the longest line
                                      //  End of loop (1)
  for(String q:s.split("\n")){        //  Loop (2) over the lines again
    z=q.split("((?<="+t+")|(?="+t+"))",2);
                                      //   Split on groups of ;{}, but keep them in the array
    for(a="",l=0;l++<m-z[0].length();a+=" "); 
                                      //   Amount of spaces we should add
    r+=z[0]+a+(z.length>1?z[1]:"")+"\n"; 
                                      //   Append this line to the result-String
  }                                   //  End of loop (2)
  return r;                           //  Return the result-String
}                                     // End of method

Hei, saya mengomentari jawaban ini, tetapi ini berlaku untuk banyak orang lain dari Anda. Kami saat ini memerlukan parameter lambda untuk memiliki tipe di Jawa .
Nathan Merrill

1
@NathanMerrill Takut hari penghakiman akan datang. Jk, akan menambahkannya mulai sekarang dan saya sudah mengedit jawaban saya, terima kasih. ;)
Kevin Cruijssen
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.