탭 대 우주 전쟁


24

탭 대 우주 전쟁

따라서 코드를 들여 쓰기 / 포맷하기 위해 탭을 사용할지 공백을 사용할 지에 대한 많은 논쟁이있었습니다. 엄청나게 미친 독특한 형식 지정 방법으로 이동하여 대학이 분쟁을 해결하도록 도울 수 있습니까?


당신의 임무는 모든 탭을 네 개의 공간으로 확장하는 전체 프로그램이나 기능을 작성하는 것입니다. 그런 다음 n 개의 선행 공백을 "/ (n-two stars) /"로 바꿉니다. 합리적인 형식으로 여러 줄에 걸쳐 입력을받습니다 (각 줄마다 줄을 배열하는 문자열, 열 배열 등).

부끄럽게 도난당한 샘플 입력 . SE에서는 탭이 자동으로 4 개의 공백으로 확장되므로 탭을 "^"문자로 나타내지 만 탭 (코드 포인트 0x09)도 처리해야합니다. 모든 "^"문자는 표를 나타냅니다.

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! 

샘플 출력

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! 

대학에 Vim과 Emacs를 모두 다운로드 할 공간이 필요하기 때문에 코드 저장 공간이 거의 없습니다. 따라서 이것은 이며 가장 짧은 코드가 승리합니다. 입력이 올바르게 구성되어 있고 탭을 교체 한 후 공백이 4 개 미만인 줄은 동작이 정의되지 않을 수 있습니다.

기권

이 "우수한"형식화 전략은 Geobits에 의해 제공되었으며 그의 허가에 따라 재생산됩니다. 이 도전 과제를 제작하는 동안 프로그래머는 해를 입지 않았습니다.


1
탭은 줄의 시작 부분에서만 나타 납니까? 줄을 들여 쓰기 할 수 있습니까 (탭 + 공백)?
Lynn

20
누군가는 공백으로 작성된 답변을 제출하십시오 .
GuitarPicker

2
로 시작하는 줄을 고려해야합니까 /*, 아니면 "잘 구성된 입력"이 아닌 것으로 간주 될 수 있습니까? C ++ 소스 파일은 여러 /* */줄 주석 이 선행 및 마지막 공백을로 대체 /하고 다음으로 공백을 채우는 일부 답변을 깨뜨릴 수 있기 때문에 더 나은 테스트 였습니다 *.
seshoumara

1
전쟁은 끝났습니다 : medium.com/@hoffa/… (C로 프로그래밍하지 않는 한)
비커

1
@RohanJhunjhunwala 이제 컴파일 가능한 코드가 아니기 때문에 첫 번째 질문을 다시합니다. 동일한 /* */C ++ 코드를 상상해보십시오. 이번에는 줄의 시작 부분에 있습니다. 귀하의 사양에 따라 그대로 유지해야합니다. 여기서 함정은 이미 잘못된 답변을 발견했습니다. 정말과 같은 정규 표현식 /\** /이 별표로 //를 채우는 데 사용 된 것과 같은 정규 표현식 은 줄을로 바꿉니다 /***/. 이 전환도 보았습니다 /*//*/. 나는 둘 다 틀렸다고 가정한다.
seshoumara

답변:


2

V , 21 , 20 바이트

Íô/    
Î^hr/hv0r*r/

온라인으로 사용해보십시오!

이것은 말 그대로 내 vim 답변의 직접적인 포트입니다. 주목할만한 차이점 :

  • Í(글로벌 대체)를 자동으로 채 웁니다 명령 /g2 바이트를 저장 플래그,

  • ô ~와 동일하다 \t

  • Î의 니모닉이며 :%norm, :%norm키 스트로크 사이 와 필요한 키 사이를 채 웁니다 .

  • 끝에 후행 캐리지 리턴이 내재적으로 추가됩니다.


27

Vim, 37, 34, 33, 32 바이트

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

온라인으로 사용해보십시오!

온라인 통역사에는 없지만 vim에는 후행 캐리지 리턴 (입력)이 필요합니다.

이전 버전과 호환되기 때문에 V 인터프리터를 사용합니다. 매우 간단한 솔루션입니다.

솔루션이 실시간으로 발생하는 것을 확인할 수있는 gif입니다. 이것은 약간 오래된 버전을 사용하며 약간의 키 입력을 추가하여 느리게 실행하여 결과를 확인할 수 있습니다.

enter image description here

작동 방식에 대한 설명은 다음과 같습니다.

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

나는 사용하기 위해 +1 g하려고했지만 g : / +1을 사용하지 않도록 편집했다 : D
Downgoat

@ downgoat Haha, 감사합니다! 실제로 :g알려지지 않은 기능을 남용하기 때문에 버전을 자랑스럽게 생각 합니다. 실패하면 norm명령이 취소됩니다 ^F<space>. 그래서 :%norm ^F<space>foo본질적으로 같은 일이 :g/^ /norm foo재미 빔 해킹. : D
DJMcMayhem

허, 나는 ^ F가 스크린을 위치 시키는데 사용되었다고 생각했다. 내부에 다른 동작이 norm있습니까?
Downgoat

1
@ downgoat Haha, ^F아닙니다. <C-f>Silly Vim 키 표기법이 아닙니다 . 이 경우에는 ^공백이 아닌 첫 번째 문자로 F<space>이동하고 커서 뒤의 첫 번째 공백을 찾습니다.
DJMcMayhem

아, 이제 훨씬 더 의미가 있습니다> _>
Downgoat

11

펄, 41 바이트

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

다음과 같이 -p플래그로 실행하십시오 .

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

탭으로 교체하십시오 Control-V Tab. Bash에서을 입력하십시오 .


1
perl그 역 참조를 그 자리에서 대체 한 방법도 그랬 으면 좋겠다 sed.
seshoumara

7

체다 , 60 57 56 바이트

@Conor O'Brien 덕분에 3 바이트 절약

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

체다가 더 나은 문자열 형식을 갖기를 바랍니다.

온라인으로 사용해보십시오!

설명

이것은 기능입니다. `ar.map (@. head (-1)) 같은 기능을 수행 할 수있는 @기능화 된 속성 (예 : ruby ​​'s &:)을 나타냅니다 .

@                      // 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
 )

정규식에 익숙하지 않은 경우 다음을 수행하십시오.

/^ +/gm

이것은 기본적으로 모든 ( ) 의 시작 ( ) 에서 하나 이상의 +공백 ( ) 과 일치 합니다 ( ).^gm


체다 탭에서 리터럴 탭이 작동합니까? 또한 /^ +/선행 공간의 길이가 4 이상이라고 가정 할 수 있기 때문에 정규 표현식으로 충분합니다.
코너 O'Brien

@ ConorO'Brien 나는 그들이 믿지만 테스트하지 않았습니다
Downgoat

변환 전에 탭을 교체해야합니다.
코너 O'Brien

@ ConorO'Brien oh> _> 나는 원래 그런 식으로 그것을 가지고 그것을 변경
Downgoat

6

수학, 97 바이트

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

익명의 기능. 문자열을 입력으로 받아서 문자열을 출력으로 반환합니다.


5

파이썬 3, 124 바이트

좋은 ol '정규식을 사용합니다.

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

무시 했어!


4

자바 (210) 207 바이트

이것이 순진하게 구현하는 참조 솔루션입니다.

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 바이트, 체다 : 65 바이트, JavaScript : 75 바이트, 210 바이트에 Java가 있습니다 : P 왜 놀랍지
않습니까

1
자바에서 매우 간결한 코드 : P
로한 Jhunjhunwala

1 바이트를 저장하기 위해 마지막 for-loop를 변경할 수 있습니다 for(int j=0;++j<i-1;). 또한 int before 를 제거하고 j이미 존재하는 int 뒤에 넣을 수 있습니다.int i=s.length()-(x=s.replaceAll("^\\s+", "")).length(),j;
Kevin Cruijssen

(a)-> {...}를 사용하여 바이트를 면도하는 람다가 될 수 없습니까?
bunyaCloven

적어도 그것은 여전히 ​​읽을 수 있고 더 이상의 주석이 필요하지 않습니다 : o)
René

3

자바 스크립트 ES6, 75 바이트

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

교체 \t코드에서 문자 탭.


3

자바 185 184 167 152 바이트

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

초기 게시물에서 주어진 문자열 배열의 정의가 매우 느슨 Stream<String>하기 때문에 결과적으로 바이트를 절약 할 수 있습니다.

같은 목표를 달성하기 위해 RI와 다른 기술을 사용했습니다. 알고리즘 자체는 다소 동일합니다.

테스트 및 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

망막 , 25 바이트

\t실제 탭 문자 (은 0x09)로 교체해야합니다.

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

온라인으로 사용해보십시오!

설명

\t
4$* 

각 탭을 4 개의 공백으로 바꾸십시오.

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

줄 의 시작 부분에 공백을 %일치 2+N시키고를 사본이 /.../있는 위치 ...로 바꾸어 각 줄을 개별적으로 변환하십시오 ( ) .N*



2

SED (-r의 경우 56 + 1) 57

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

어디 탭입니다
공백 1. 대체합니다 탭.
2. 첫 번째와 마지막 선행 공간을로 바꿉니다 /.
3. /및 0+ *s 이후의 첫 번째 공백 *이 일치하지 않을 때까지 대체합니다 .


sed가 지정되었으므로 다른 sed 답변에서 -r ''을 제거하는 것과 마찬가지로 코드 주위에 작은 따옴표가 필요하지 않습니다. 스크립트는 -f. n 또는 r과 같은 추가 플래그는 각각 1 바이트로 계산해야합니다. 따라서 여기에서는 2 바이트를 저장합니다.
seshoumara

그것이 제가 생각한 것이지만 확실합니다. 감사.
라일리

;T 명령 후 어느 필요가 없습니다. 코드 자체는 세 번째 s명령 의 시작 부분에 ^가 필요합니다 . 그렇지 않으면 "3/5"와 같은 입력이 "3 / * 5"로 바뀝니다. 첫 번째 s명령 에는 실제로 탭이 있지만 올바르게 표시되지 않고 오도되기 때문에 \ t를 사용하거나 이후에 지정하면 해당 문자는 탭이었습니다.
seshoumara

@seshoumara 고마워, 내 휴대 전화에서 게시하려고합니다 ... 가장 쉬운 방법은 아닙니다.
라일리

다른 답변을 합한 것 보다이 답변을 편집하는 데 더 많은 시간을 보냈다고 생각합니다. 도와 주셔서 감사합니다!
라일리

1

대학은 Emacs Lisp (또는 기본적으로 tabify또는 untabify단독으로) 프로그램 이 Java보다 훨씬 장황하므로 프로그램을위한 더 많은 공간을 허용해야합니다 . 또한 식별 크기가 4보다 작거나 C와 유사한 언어로 코딩하는 학생 (또는 교사)에게 세심한주의를 기울여야합니다.

다음 솔루션은 206 바이트입니다.

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

tab-width명시 적으로 설정할 필요가 없다고 가정하면 20 개를 절약 할 수 있습니다.

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

그리고 ungolfed 버전은 다음과 같습니다

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

우리는 먼저 untabify 는 시작하기 전에 지역을 시작합니다. 그런 다음 줄의 시작 부분에 공백이있는 반면 공백이있는 주석으로 대체합니다. 정확히 말하면 삽입되는 주석은 다음과 같이 구성됩니다.

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

자체는 97 바이트를 차지합니다. 일부 문자열을 n 번 복사하는 더 짧은 솔루션이 높이 평가됩니다.


1

루비, 52 47 + 1 (p 플래그) = 48 바이트

편집 : Value Ink 덕분에 전체 5 바이트 저장

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

1
p플래그를 사용하여 (g) sub $_가 인쇄 된 값을 수정 하여 변경 한다는 사실을 이용할 수 있습니까 ? ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'
Value Ink

고마워, 나는 (g)subbang 이 없으면 $_여기서 수정할 수 있다는 것을 몰랐다 .
michau

1

GNU sed, 66 64 + 1 (r 플래그) = 65 바이트

편집 : Riley 의 제안 덕분에 1 바이트가 적습니다 .

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

운영: sed -rf formatter.sed input_file

로 분리하는 이유는 \n그렇지 않으면 C ++ 라인이 같은 코멘트로 시작하기 때문에 그 행의 텍스트의 나머지 부분에서 최고의 공간입니다 /* */으로 회전을 것 /*****/같은 단순한 라인 4 s,^(/\**) ,\1*,또는 s,^(/\**) ( */),\1*\2,. sed는 각 입력 라인에 대해 스크립트를 실행하므로 \n읽을 때 패턴 공간에 no 가 도입 되지 않습니다 .


/를 교체 할 때까지 닫기를 넣지 않으면 바이트를 절약 할 수 있습니다 \n. 4 번 라인에서 일치시킬 필요가 없습니다.
Riley

@Riley 잘 잡아라. 코드를 업데이트했습니다.
seshoumara

\t탭 문자 로 바꾸어 다른 문자를 저장할 수 있습니다 .
라일리

@Riley 사실이지만 탭으로 인쇄되지 않기 때문에 의심 스럽다. 바이트 수를보다 경쟁력있는 미래의 sed 답변에 대해이 점을 명심하십시오.
seshoumara
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.