Kết thúc các tab so với không gian chiến tranh


24

Kết thúc các tab so với không gian chiến tranh

Vì vậy, đã có rất nhiều tranh luận về việc nên sử dụng các tab hoặc khoảng trắng để thụt lề / định dạng mã. Bạn có thể giúp các trường đại học giải quyết tranh chấp, bằng cách đi đến một phương pháp định dạng độc đáo vô cùng điên rồ .


Công việc của bạn là viết một chương trình hoặc chức năng đầy đủ để mở rộng tất cả các tab thành bốn không gian. Và sau đó thay thế một chuỗi n khoảng trắng bằng "/ (n - hai ngôi sao ở đây) /". Bạn sẽ nhận được đầu vào trên nhiều dòng ở bất kỳ định dạng hợp lý nào (mảng chuỗi đơn cho mỗi dòng mới. Mảng cột, v.v.)

Mẫu đầu vào xấu hổ bị đánh cắp . Lưu ý rằng vì các tab được mở rộng tự động thành bốn khoảng trắng trên SE, tôi biểu thị nó là ký tự "^", nhưng bạn cũng phải xử lý các tab (codepoint 0x09). Tất cả các ký tự "^" đại diện cho một bảng.

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! 

Sản lượng mẫu

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! 

Vì trường đại học cần không gian để tải xuống cả Vim và Emacs, bạn được phép lưu trữ rất ít cho mã của mình. Do đó, đây là và mã ngắn nhất sẽ thắng. Bạn có thể cho rằng đầu vào được hình thành tốt và các dòng có ít hơn bốn khoảng trắng (sau khi thay thế các tab) có thể dẫn đến hành vi không xác định.

Khước từ

Chiến lược định dạng "xuất sắc" này được cung cấp bởi Geobits và được sao chép lại với sự cho phép của anh ta. Không có lập trình viên nào bị tổn hại trong quá trình sản xuất thử thách này.


1
Các tab sẽ chỉ xảy ra ở đầu dòng (tức là thụt lề)? Các dòng có thể thụt lề hỗn hợp (tab + dấu cách) không?
Lynn

20
Ai đó vui lòng gửi câu trả lời được viết trong Khoảng trắng .
GuitarPicker

2
Chúng ta có nên xem xét các dòng bắt đầu bằng /*, hoặc có thể được coi là không phải là "đầu vào được hình thành tốt" không? Một tệp nguồn C ++ sẽ là một thử nghiệm tốt hơn, bởi vì nhận xét đa dòng của nó /* */có thể phá vỡ một số câu trả lời thay thế đầu tiên và cuối cùng của không gian hàng đầu bằng một /, và sau đó tiến hành điền vào chỗ trống *.
seshoumara

1
Cuộc chiến đã kết thúc: Medium.com/@hoffa/ ((Trừ khi bạn lập trình bằng C, rõ ràng.)
cốc cốc

1
@RohanJhunjhunwala Vì vậy, bây giờ tôi hỏi lại câu hỏi đầu tiên của mình, vì đó không phải là về mã có thể biên dịch được. Tưởng tượng cùng /* */mã C ++, nhưng lần này ở đầu dòng. Theo thông số kỹ thuật của bạn, nó nên được để lại như là. Đây là cái bẫy và đã phát hiện ra các câu trả lời sai, rằng một biểu thức chính quy /\** /được sử dụng để lấp đầy các khoảng trống giữa // bằng dấu hoa thị sẽ biến dòng thành /***/. Tôi cũng đã thấy chuyển đổi này /*//*/. Tôi cho rằng cả hai đều không chính xác.
seshoumara

Câu trả lời:


2

V , 21 , 20 byte

Íô/    
Î^hr/hv0r*r/

Hãy thử trực tuyến!

Đây thực sự chỉ là một cổng trực tiếp của câu trả lời vim của tôi. Sự khác biệt đáng chú ý:

  • Các Ílệnh (Toàn cầu thay thế) sẽ tự động điền vào /glá cờ, mà tiết kiệm hai byte

  • ô giống hệt với \t

  • ÎLà một bản ghi nhớ cho :%norm, và nó cũng lấp đầy khoảng trống cần thiết giữa :%normvà bộ tổ hợp phím.

  • Sự trở lại vận chuyển cuối cùng được thêm vào ngầm.


27

Vim, 37, 34, 33, 32 byte

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

Hãy thử trực tuyến!

Lưu ý rằng điều này đòi hỏi một sự trở lại vận chuyển kéo dài (enter) trong vim, mặc dù không có trong trình thông dịch trực tuyến.

Cái này sử dụng trình thông dịch V vì nó tương thích ngược. Một giải pháp rất đơn giản.

Đây là một gif cho phép bạn thấy giải pháp xảy ra trong thời gian thực. Cái này sử dụng một phiên bản cũ hơn một chút và tôi đã thêm một số tổ hợp phím bổ sung để làm cho nó chạy chậm hơn để bạn có thể thấy điều gì xảy ra:

nhập mô tả hình ảnh ở đây

Và đây là lời giải thích về cách thức hoạt động của nó:

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

Tôi sẽ +1 để sử dụng gnhưng sau đó bạn đã chỉnh sửa để không sử dụng g: / +1: D
Downgoat

@downgoat Haha, cảm ơn! Tôi thực sự tự hào hơn nhiều về phiên bản mà không :gvì nó lạm dụng một tính năng ít được biết đến: normlệnh bị hủy nếu ^F<space>thất bại. Vì vậy, :%norm ^F<space>foovề cơ bản là điều tương tự như :g/^ /norm foohack Vim vui vẻ. : D
DJMcMayhem

huh, tôi nghĩ ^ F đã được sử dụng để đăng màn hình. bên trong nó có hành vi khác nhau normkhông?
Hạ cấp

1
@downgoat Haha, không ^F, không phải <C-f>ký hiệu khóa Silly Vim. Trong trường hợp này ^, hãy chuyển đến char không phải khoảng trắng đầu tiên và F<space>đó là tìm khoảng trống đầu tiên phía sau con trỏ.
DJMcMayhem

ohhh, điều đó có ý nghĩa hơn rất nhiều bây giờ> _>
Downgoat

11

Perl, 41 byte

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

Chạy với -pcờ, như vậy:

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

Thay thế bằng một tab (trong Bash, hãy thử gõ Control-V Tab.)


1
Cách perlthay thế sự phản ứng đó ngay tại chỗ, tôi cũng muốn sedđiều đó.
seshoumara

7

Cheddar , 60 57 56 byte

Đã lưu 3 byte nhờ @Conor O'Brien

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

Tôi muốn Cheddar có định dạng chuỗi tốt hơn.

Hãy thử trực tuyến!

Giải trình

Đây là một chức năng. @là một thuộc tính có chức năng đại diện (ví dụ như ruby &:) cho phép bạn làm những việc như: `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
 )

Nếu bạn không quen thuộc với regex, hãy:

/^ +/gm

điều này về cơ bản khớp với một hoặc nhiều +khoảng trắng ( ) khoảng trống ( ) ở đầu ( ^) của mọi gdòng ( m) ( ).


các tab nghĩa đen làm việc trong regexes cheddar? Ngoài ra, /^ +/đủ là một regex, vì chúng ta có thể giả định rằng các không gian hàng đầu sẽ có ít nhất 4 chiều dài.
Conor O'Brien

@ ConorO'Brien Tôi tin rằng họ làm nhưng tôi chưa thử nghiệm
Downgoat

Các tab được cho là sẽ được thay thế trước khi chuyển đổi.
Conor O'Brien

@ ConorO'Brien oh> _> Tôi đã có nó theo cách đó ban đầu và sau đó tôi đã thay đổi nó
Downgoat

6

Toán học, 97 byte

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

Chức năng ẩn danh. Lấy một chuỗi làm đầu vào và trả về một chuỗi là đầu ra.


5

Python 3, 124 byte

Sử dụng regex ol 'tốt.

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

Nghĩa là nó!


4

Java 210 207 byte

Đây là giải pháp tham khảo thực hiện nó một cách ngây thơ.

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, sau đó có Java ở mức 210 byte: P tại sao tôi không ngạc nhiên
Downgoat

1
Mã rất súc tích trong java: P
Rohan Jhunjhunwala

Bạn có thể thay đổi vòng lặp for cuối cùng để lưu 1 byte : for(int j=0;++j<i-1;). Ngoài ra, bạn có thể xóa phần int trước jvà đặt nó sau phần int đã có:int i=s.length()-(x=s.replaceAll("^\\s+", "")).length(),j;
Kevin Cruijssen

không thể là lambda để cạo byte bằng cách sử dụng (a) -> {...}?
bunyaCoppy

Ít nhất nó vẫn có thể đọc được và không cần bình luận thêm: o)
René

3

JavaScript ES6, 75 byte

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

Thay thế \tbằng một tab bằng chữ trong mã của bạn.


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

Đưa ra định nghĩa rất lỏng lẻo của chuỗi chuỗi được đưa ra trong bài viết ban đầu, tôi đã sử dụng Stream<String>cho phép tiết kiệm byte do đó.

Tôi đã sử dụng các kỹ thuật khác với RI để đạt được cùng một mục tiêu. Các thuật toán chính nó là giống nhau.

Kiểm tra và không được phép :

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

Võng mạc , 25 byte

Các \tnên được thay thế bằng một ký tự tab thực tế (0x09).

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

Hãy thử trực tuyến!

Giải trình

\t
4$* 

Thay thế mỗi tab bằng bốn khoảng trắng.

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

Chuyển đổi mỗi dòng riêng ( %) bằng cách kết hợp 2+Nkhoảng trắng ở đầu dòng và thay thế nó bằng /.../nơi ...Nbản sao của *.



2

SED (56 + 1 cho -r) 57

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

Trường hợp một tab
1. thay thế các tab bằng dấu cách.
2. thay thế không gian hàng đầu đầu tiên và cuối cùng với /.
3. thay thế khoảng /trắng đầu tiên sau và 0+ *s *cho đến khi không có kết quả khớp.


Vì sed được chỉ định, nên không có dấu ngoặc đơn nào xung quanh mã, giống như xóa -r '' khỏi các câu trả lời sed khác của bạn, bởi vì bạn có thể coi tập lệnh như được lưu trữ trong tệp nguồn mà bạn chạy cùng -f. Bất kỳ cờ bổ sung nào được sử dụng như n hoặc r nên được tính là một byte mỗi. Vì vậy, ở đây, bạn tiết kiệm 2 byte.
seshoumara

Đó là những gì tôi nghĩ, nhưng tôi muốn chắc chắn. Cảm ơn.
Riley

Lệnh ;sau cũng không cần thiết. Đối với bản thân mã, bạn cần một ^ ở đầu slệnh thứ ba , nếu không, một đầu vào như "3/5" này được chuyển thành "3 / * 5". Trong slệnh đầu tiên bạn thực sự có một tab ở đó, nhưng nó không được hiển thị chính xác và gây hiểu lầm, vì vậy, sử dụng \ t hoặc chỉ định sau, char đó là một tab.
seshoumara

@seshoumara Cảm ơn, tôi đang cố gắng đăng bài từ điện thoại của mình ... Đây không phải là điều dễ nhất để làm.
Riley

Tôi nghĩ rằng tôi đã dành nhiều thời gian để chỉnh sửa câu trả lời này hơn tất cả những câu hỏi khác cộng lại. Cảm ơn đã giúp đỡ!
Riley

1

Trường đại học nên xem xét cho phép thêm một chút không gian cho các chương trình trong Emacs Lisp (hoặc mặc định tabifyuntabifymột mình), vì chúng thậm chí còn dài dòng hơn Java. Nó cũng nên chú ý đến các sinh viên (hoặc giáo viên) có kích thước nhận dạng nhỏ hơn bốn hoặc những người tình cờ viết mã bằng một số ngôn ngữ không giống như C.

Giải pháp sau đây có 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)))))))))

Giả sử rằng tab-widthkhông cần phải được thiết lập rõ ràng, chúng ta có thể lưu 20 trong số chúng.

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

Và phiên bản không có người trông sẽ như thế này

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

Chúng tôi đầu tiên untabifykhu vực trước khi bắt đầu. Sau đó, trong khi chúng ta thấy khoảng trắng ở đầu một dòng, chúng ta thay thế nó bằng một nhận xét dài như khoảng trắng đã nói. Nói chính xác, bình luận được chèn vào được xây dựng bởi

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

mà chính nó chiếm 97 byte. Một giải pháp ngắn hơn để sao chép một số chuỗi n lần được đánh giá cao.


1

Ruby, 52 47 + 1 (cờ p) = 48 byte

Chỉnh sửa : đã lưu toàn bộ 5 byte, nhờ vào Value Ink

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

1
Bạn có thể sử dụng pcờ để tận dụng thực tế là (g) phụ sửa đổi $_và do đó thay đổi giá trị in không? ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'
Mực giá trị

Cảm ơn, tôi không biết (g)subnếu không có tiếng nổ có thể sửa đổi $_ở đây.
michau

1

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

Chỉnh sửa: Giảm 1 byte nhờ đề xuất của Riley .

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

Chạy: sed -rf formatter.sed input_file

Lý do để phân tách với một \nkhoảng trắng hàng đầu từ phần còn lại của văn bản trên dòng đó là bởi vì nếu không thì một dòng C ++ bắt đầu bằng một nhận xét như thế này /* */sẽ bị biến thành /*****/một dòng 4 đơn giản hơn s,^(/\**) ,\1*,hoặc thậm chí s,^(/\**) ( */),\1*\2,. Vì sed thực thi tập lệnh cho từng dòng đầu vào, nên không có phần nào \nđược đưa vào không gian mẫu khi đọc.


Bạn có thể lưu một byte bằng cách không đóng vào /cho đến khi bạn thay thế \n. Điều đó giúp bạn tiết kiệm được việc phải khớp nó trong dòng 4.
Riley

@Riley Bắt tốt. Cập nhật mã.
seshoumara

Bạn có thể lưu cái khác bằng cách thay thế \tbằng một ký tự tab.
Riley

@Riley Điều đó là đúng, nhưng vì nó sẽ không được in dưới dạng tab ở đây, tôi nghi ngờ. Tôi sẽ ghi nhớ điều này cho các câu trả lời sed trong tương lai với số byte cạnh tranh hơn.
seshoumara
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.