세상에, 공간이 가득합니다!


42

어떤 사람들은 표와 들여 쓰기를 위해 공백을 사용해야한다고 주장합니다.

도표를 위해, 그것은 틀림없이 틀렸다. 정의에 따라 테이블을 사용하여 테이블을 사용해야합니다.

들여 쓰기의 경우에도 타블로 터는 객관적으로 우수합니다.

  • Stack Exchange 커뮤니티 에는 명확한 합의 가 있습니다.

  • 들여 쓰기를 위해 단일 공간을 사용하는 것은 시각적으로 불쾌합니다. 둘 이상을 사용하는 것은 낭비입니다.

    모든 골프 선수들이 알고 있듯이 프로그램은 가능한 짧아야합니다. 하드 디스크 공간을 절약 할뿐 아니라 적은 바이트를 처리해야하는 경우 컴파일 시간도 줄어 듭니다.

  • 탭 너비 1 을 조정하면 각 컴퓨터에서 동일한 파일이 다르게 보이므로 모든 사람이 실제 파일을 수정하지 않고도 좋아하는 들여 쓰기 너비를 사용할 수 있습니다.

  • 모든 훌륭한 텍스트 편집기는 기본적으로 tabulator를 사용합니다 (및 정의).

  • 나는 그렇게 말하고 나는 항상 옳다!

슬프게도 모든 사람이 이성을 듣는 것은 아닙니다. 누군가 잘못된 TM 파일을 보냈으므로 수정해야합니다. 수동으로 할 수도 있지만 다른 것들도 있습니다.

스페이서가 귀중한 시간을 낭비하고 있기 때문에 문제가 해결 될 수있는 가장 짧은 프로그램을 작성하기로 결정했습니다.

태스크

다음을 수행하는 프로그램이나 함수를 작성하십시오.

  1. STDIN에서 또는 명령 행 또는 함수 인수로 단일 문자열을 읽으십시오.

  2. 공백이 표 또는 들여 쓰기에 사용 된 모든 위치를 식별하십시오.

    줄의 시작 부분 에 공백이 있으면 들여 쓰기가 됩니다.

    의 실행 두 개 이상의 공간은 가 들여 쓰기되지 않습니다.

    하나의 들여 쓰기없는 공간이나 표에 사용되지 않았을 수 있습니다. 다른 목적으로 같은 캐릭터를 사용할 때 예상 할 수 있듯이 쉽게 알 수있는 방법은 없습니다. 따라서 공간이 혼란 에 사용되었다고 말할 것입니다 .

  3. 파일 모양을 변경하지 않고 테이블 또는 들여 쓰기에 사용 된 모든 공간을 테이블로 대체 할 수 있는 가장 긴 탭 너비 1 을 결정 하십시오.

    입력에 표 또는 들여 쓰기가 포함되어 있지 않으면 탭 너비를 결정할 수 없습니다. 이 경우 다음 단계를 건너 뜁니다.

  4. 이전에 결정된 탭 너비를 사용하여 테이블 또는 들여 쓰기에 사용 된 모든 공간을 테이블로 대체하십시오.

    또한 파일 모양을 변경하지 않고 가능할 때마다 혼동에 사용 된 모든 공간을 테이블로 대체하십시오. (의문이 있으면 공백을 제거하십시오.)

  5. 함수에서 수정 된 문자열을 반환하거나 STDOUT에 인쇄하십시오.

  • 모든 공간

    a    bc   def  ghij
    

    표입니다.

    각 공백은 공백이 아닌 문자의 앞 문자열을 너비 5로 채 웁니다. 따라서 올바른 탭 너비는 5이고 올바른 출력 2

    a--->bc-->def->ghij
    
  • 처음 두 공간

    ab  cde f
    ghi jk lm
    

    표, 다른 사람들은 혼란입니다.

    올바른 탭 너비는 4이므로 올바른 출력 2

    ab->cde>f
    ghi>jk lm
    

    마지막 공간은 테이블 로 대체되면 공간 으로 렌더링되므로 그대로 유지 됩니다.

    ab->cde>f
    ghi>jk->lm
    
  • 한 칸만 빼고

    int
        main( )
        {
            puts("TABS!");
        }
    

    들여 쓰기, 다른 하나는 혼란입니다.

    들여 쓰기 레벨은 0, 4 및 8 공백이므로 올바른 탭 너비는 4이고 올바른 출력 2

    int
    --->main( )
    --->{
    --->--->puts("TABS!");
    --->}
    

    공간에서이 ( )태뷸로 대체하는 경우는 그대로 남아 있으므로, 세 구역으로 렌더링 될 것이다.

  • 처음 두 공간

      x yz w
    

    들여 쓰기, 다른 혼란입니다.

    올바른 탭 너비는 2이고 올바른 출력 2

    ->x>yz w
    

    마지막 공간은 테이블로 대체되면 두 공간으로 렌더링되므로 그대로 유지됩니다.

  • 처음 두 공간

      xy   zw
    

    들여 쓰기, 다른 세는 표입니다.

    탭 너비가 1이면 모든 공백을 제거 할 수 있으므로 올바른 출력 2

    >>xy>>>zw
    
  • 모든 공간

    a b c d
    

    혼란입니다.

    가능한 가장 긴 탭 너비가 없으므로 올바른 출력 2

    a b c d
    

추가 규칙

  • 입력은 전적으로 인쇄 가능한 ASCII 문자와 줄 바꿈으로 구성됩니다.

  • 한 줄에 최대 100 줄의 텍스트가 있고 최대 100자가 있다고 가정 할 수 있습니다.

  • 출력을 위해 STDOUT을 선택하면 단일 후행 줄 바꿈을 인쇄 할 수 있습니다.

  • 표준 규칙이 적용됩니다.


1 탭 너비는 고정 폭 글꼴을 사용하여 두 개의 연속 탭 정지 사이의 문자 간격으로 정의됩니다 .
2 ASCII 아트 화살표는 스택 교환이 제대로 렌더링하기를 거부하는 표를 나타냅니다. 버그 보고서를 제출했습니다. 실제 출력에는 실제 테이블 레이터가 포함되어야합니다.


9
넌센스

2
programs should be as short as possible아서 휘트니의 잃어버린 오빠를 찾았다 고 생각합니다 !!
kirbyfan64sos


13
탭은 자신의 비트가 찢어지고 자격이없는 영혼이 부족해질 때까지 ASCII 코드가 치명적일 수있는 악의없는 악마입니다. 어라운드하지만 신성 모독에도 불구하고 +1, 좋은 도전입니다. ;)
도어 손잡이

1
동료가 내 아름다운 공간 들여 쓰기 코드에 탭을 추가 할 때마다 울고있었습니다. 그런 다음 Visual Studio에서 CTRL + K + F를 발견했습니다. 수정 된 파일을 열 때마다 수행합니다. 내 인생은 이제 더 좋아
Michael M.

답변:


5

Pyth, 102 103 바이트

=T|u?<1hHiGeHGsKmtu++J+hHhGlhtH+tG]+HJ.b,YN-dk<1u+G?H1+1.)Gd]0]0cR\ .zZ8VKVNp?%eNT*hNd*/+tThNTC9p@N1)pb

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

재미있는 아이디어이지만 입력의 탭으로 인해 개념이 깨지기 때문에 유용하지 않습니다.

편집 : 버그 수정. 많은 감사합니다 @aditsu


"abc d"에서 충돌
aditsu

@aditsu 쓰레기! 고마워요. 더 나은 테스트 사례가 필요합니다 : P
Brian Tuck

5

PowerShell, 414 409 바이트

function g($a){if($a.length-gt2){g $a[0],(g $a[1..100])}else{if(!$a[1]){$a[0]}else{g $a[1],($a[0]%$a[1])}}}{$a[0]}else{g $a[1],($a[0]%$a[1])}}}
$b={($n|sls '^ +|(?<!^)  +' -a).Matches}
$n=$input-split"`n"
$s=g(&$b|%{$_.Index+$_.Length})
($n|%{$n=$_
$w=@(&$b)
$c=($n|sls '(?<!^| ) (?! )'-a).Matches
$w+$c|sort index -d|%{$x=$_.Index
$l=$_.Length
if($s-and!(($x+$l)%$s)){$n=$n-replace"(?<=^.{$x}) {$l}",("`t"*(($l/$s),1-ge1)[0])}}
$n})-join"`n"

나는 ;디스플레이를 더 쉽게 만들기 위해 가능한 대신 개행을 사용했습니다 . 유닉스 줄 끝을 사용하고 있으므로 바이트 수에 영향을 미치지 않아야합니다.

실행하는 방법

코드를 SpaceMadness.ps1파일 로 복사 한 다음 입력을 스크립트로 파이프하십시오. 변환이 필요한 파일을 다음과 같이 가정합니다 taboo.txt.

PowerShell에서 :

cat .\taboo.txt | .\SpaceMadness.ps1

명령 프롬프트에서 :

type .\taboo.txt | powershell.exe -File .\SpaceMadness.txt

PowerShell 5로 테스트했지만 3 이상에서 작동합니다.

테스팅

위의 테스트에 유용한 빠른 PowerShell 스크립이 있습니다.

[CmdletBinding()]
param(
    [Parameter(
        Mandatory=$true,
        ValueFromPipeline=$true
    )]
    [System.IO.FileInfo[]]
    $File
)

Begin {
    $spaces = Join-Path $PSScriptRoot SpaceMadness.ps1
}

Process {
     $File | ForEach-Object {
        $ex = Join-Path $PSScriptRoot $_.Name 
        Write-Host $ex -ForegroundColor Green
        Write-Host ('='*40) -ForegroundColor Green
        (gc $ex -Raw | & $spaces)-split'\r?\n'|%{[regex]::Escape($_)} | Write-Host -ForegroundColor White -BackgroundColor Black
        Write-Host "`n"
    }
}

같은 디렉토리에 넣고 SpaceMadness.ps1, 나는이 하나의 호출 tester.ps1과 같이 호출 :

"C:\Source\SomeFileWithSpaces.cpp" | .\tester.ps1
.\tester.ps1 C:\file1.txt,C:\file2.txt
dir C:\Source\*.rb -Recurse | .\tester.ps1

당신은 아이디어를 얻습니다. 변환 후 각 파일의 내용을 뱉어 내고 [RegEx]::Escape()공백과 탭을 모두 벗어나므로 실제로 변경된 내용을 보는 것이 매우 편리합니다.

출력은 다음과 같습니다 (색상 포함).

C:\Scripts\Powershell\Golf\ex3.txt
========================================
int
\tmain\(\ \)
\t\{
\t\tputs\("TABS!"\);
\t}

설명

첫 번째 줄은 g배열 (임의의 수)을 취하고 Euclidean 알고리즘을 사용하여 재귀 적으로 GCD를 계산 하는 가장 큰 공통 요소 / 제수 함수 를 간결하게 정의합니다 .

이것의 목적은 질문에 정의 된 모든 들여 쓰기표의 색인 + 길이 를 가져 와서이 함수에 공급하여 우리가 할 수있는 최선의 GCD를 얻음으로써 "가장 긴 탭 너비"를 파악하는 것이 었습니다 탭 너비를 처리하십시오. 혼란의 길이는 항상 1이므로이 계산에는 아무런 영향을 미치지 않습니다.

$b귀찮게 코드 조각을 두 번 호출해야하기 때문에 scriptblock을 정의하므로 바이트를 절약합니다. 이 블록은 문자열 (또는 문자열의 배열을) 소요 $n과 (에 정규식을 실행 sls하거나 Select-String일치하는 객체를 반환). 나는 실제로 여기에 들여 쓰기와 표를 모두 가져오고있어 개별적으로 캡처하여 추가 처리를 절약했습니다.

$n는 메인 루프 내부와 외부의 다른 것들에 사용됩니다 (정말 나쁘지만 여기서는 $b스크립트 블록에 포함시키고 긴 param()선언과 전달 인수 없이 루프 내부와 외부에서 사용할 수 있도록해야합니다 .

$s$b입력 파일의 행 배열 에서 블록을 호출 한 다음 각 일치의 색인과 길이를 합산하여 합계의 배열을 인수로 GCD 함수에 반환 하여 탭 너비를 지정합니다 . 이제 $s탭의 크기가 멈췄습니다.

그런 다음 루프가 시작됩니다. 입력 라인 배열의 각 라인을 반복합니다 $n. 루프에서 가장 먼저하는 일은 $n위의 이유로 현재 줄의 값을 할당 (로컬 범위)하는 것입니다.

$w 현재 행에 대해서만 스크립트 블록 호출 값을 가져옵니다 (현재 행에 대한 들여 쓰기 및 표).

$c비슷한 값을 얻지 만 대신 모든 혼란을 찾습니다 .

나는까지 추가 $w하고 $c나에게 내가 필요로하는 공간의 일치를 모두 하나 개의 배열주는 배열되는 sort인덱스를 내림차순으로, 현재 라인에 대한 각각의 일치를 통해 반복하는 시작.

정렬이 중요합니다. 초기에 나는 대체 문자열이 더 작고 문자열의 길이를 바꿀 때 인덱스 값을 기반으로 문자열 부분을 교체하는 것이 나쁜 생각이라는 어려운 방법을 발견했습니다! 다른 인덱스는 무효화됩니다. 따라서 각 줄에서 가장 높은 색인으로 시작하여 문자열을 끝에서 더 짧게 만들고 뒤로 이동하여 색인이 항상 작동하도록합니다.

이 루프로 $x현재 일치 색인에 있으며 현재 일치 $l길이입니다. $s실제로 될 수 0있고 그로 인해 0으로 오류를 나누는 오류가 발생하므로 유효성을 검사하고 수학을 수행합니다.

!(($x+$l)%$s)비트 내가 있는지 확인 단일 지점이 혼란이 탭 여부로 교체해야합니다. 탭 폭으로 나눈 지수를 더한 길이가 더 나머지가없는 경우, 우리는있는 거 좋은 (탭으로이 경기를 교체로 이동하는 수학됩니다에 항상 작업 들여 쓰기도표화 크기가 탭 폭을 결정 무엇 때문에, 우선 첫째로).

바꾸기의 경우, 일치 루프의 각 반복은 입력의 현재 행에서 작동하므로 누적 된 대체 세트입니다. 정규 표현식 $l$x문자 가 앞에 오는 공백을 찾습니다 . $l/$s탭 문자로 대체합니다 (또는 숫자가 0 미만인 경우 1).

이 부분은 (($l/$s),1-ge1)[0]말의 멋진 뒤얽힌 방법 if (($l/$s) -lt 0) { 1 } else { $l/$s }또는 대안 [Math]::Max(1,($l/$s)). $l/$sand 의 배열을 1만든 다음 -ge 11 이상의 요소 만 포함하는 배열을 반환하는 데 사용하고 첫 번째 요소를 사용합니다. [Math]::Max버전 보다 몇 바이트 짧습니다 .

따라서 모든 교체가 완료되면 현재 줄이 ForEach-Object( %) 반복 에서 반환되고 모든 줄이 반환되면 ( 고정 줄 배열) 줄 -join바꿈이 시작됩니다 (처음에 줄 바꿈으로 분할되기 때문에).

나는 지금 당장 잡기에는 너무 타 버린 개선의 여지가 있다고 생각하지만 나중에 뭔가를 보게 될 것입니다.

탭 4 lyfe


4

PHP- 278 210 바이트

이 기능은 값 100, 라인의 최대 길이 및 최대 탭 너비로 시작하여 각 탭 너비를 테스트하여 작동합니다.

각 탭 너비에 대해 각 줄을 해당 길이의 "블록"으로 분할합니다. 이 블록 각각에 대해 :

  • 이전 블록의 마지막 문자를이 블록과 연결하여 문자 앞에 두 개의 연속 공백을 찾으면 모양을 변경하지 않고 공백으로 변환 할 수없는 들여 쓰기 또는 표가 있습니다. 다음 탭 너비를 사용해보십시오.
  • 그렇지 않으면 마지막 문자가 공백이면 블록 끝에서 공백을 제거하고 표를 추가하고 모든 것을 기억합니다.
  • 그렇지 않으면, 우리는 단지 블록을 기억합니다.

라인의 각 블록이 분석되면 라인 피드를 기억합니다. 모든 라인의 모든 블록이 성공적으로 분석되면 기억 한 문자열을 반환합니다. 그렇지 않으면 엄격하게 양의 탭 너비를 모두 시도한 경우 테이블이나 들여 쓰기가 없으며 원래 문자열을 반환합니다.

function($s){for($t=101;--$t;){$c='';foreach(split('
',$s)as$l){$e='';foreach(str_split($l,$t)as$b){if(ereg('  [^ ]',$e.$b))continue 3;$c.=($e=substr($b,-1))==' '?rtrim($b).'   ':$b;}$c.='
';}return$c;}return$s;}

ungolfed 버전은 다음과 같습니다.

function convertSpacesToTabs($string)
{
    for ($tabWidth = 100; $tabWidth > 0; --$tabWidth)
    {
        $convertedString = '';
        foreach (explode("\n", $string) as $line)
        {
            $lastCharacter = '';
            foreach (str_split($line, $tabWidth) as $block)
            {
                if (preg_match('#  [^ ]#', $lastCharacter.$block))
                {
                    continue 3;
                }

                $lastCharacter = substr($block, -1);
                if ($lastCharacter == ' ')
                {
                    $convertedString .= rtrim($block) ."\t";
                }
                else
                {
                    $convertedString .= $block;
                }
            }

            $convertedString .= "\n";
        }

        return $convertedString;
    }

    return $string;
}

2 바이트를 절약 한 DankMemes 에게 특별한 감사를드립니다 .


1
for($t=101;--$t;)for($t=100;$t;--$t)
DankMemes

4

CJam, 112

qN/_' ff=:e`{0:X;{_0=X+:X+}%}%_:+{~;\(*},2f=0\+{{_@\%}h;}*:T;\.f{\~\{@;1$({;(T/)9c*}{\;T{T%}&S9c?}?}{1$-@><}?}N*

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

나는이 혐오의 세계를 없애기 위해 내 역할을해야하므로이 도전에 대답해야했다. 탭은 분명히 우수하지만 슬프게도 일부 사람들은 추론 할 수 없습니다.

설명:

qN/          read input and split into lines
_            duplicate the array (saving one copy for later)
' ff=        replace each character in each line with 0/1 for non-space/space
:e`          RLE-encode each line (obtaining chunks of spaces/non-spaces)
{…}%         transform each line
  0:X;       set X=0
  {…}%       transform each chunk, which is a [length, 0/1] array
    _0=      copy the first element (the length)
    X+:X     increment X by it
    +        and append to the array; this is the end position for the chunk
_            duplicate the array (saving one copy for later)
:+           join the lines (putting all the chunks together in one array)
{…},         filter the array using the block to test each chunk
  ~          dump the chunk (length, 0/1, end) on the stack
  ;          discard the end position
  \(         bring the length to the top and decrement it
  *          multiply the 2 values (0/1 for non-space/space, and length-1)
              the result is non-zero (true) iff it's a chunk of at least 2 spaces
2f=          get all the end positions of the multiple-space chunks
0\+          prepend a 0 to deal with the empty array case
{…}*         fold the array using the block
  {_@\%}h;   calculate gcd of 2 numbers
:T;          save the resulting value (gcd of all numbers) in variable T
\            swap the 2 arrays we saved earlier (input lines and chunks)
.f{…}        for each chunk and its corresponding line
  \~         bring the chunk to the top and dump it on the stack
              (length, 0/1, end position)
  \          swap the end position with the 0/1 space indicator
  {…}        if 1 (space)
    @;       discard the line text
    1$(      copy the chunk length and decrement it
    {…}      if non-zero (multiple spaces)
      ;      discard the end position
      (T/)   divide the length by T, rounding up
      9c*    repeat a tab character that many times
    {…}      else (single space)
      \;     discard the length
      T{…}&  if T != 0
        T%   calculate the end position mod T
      S9c?   if non-zero, use a space, else use a tab
    ?        end if
  {…}        else (non-space)
    1$-      copy the length and subtract it from the end position
              to get the start position of the chunk
    @>       slice the line text beginning at the start position
    <        slice the result ending at the chunk length
              (this is the original chunk text)
  ?          end if
N*           join the processed lines using a newline separator

1

PowerShell을 , 165 160 153 152 142 138 137 바이트

param($s)@((0..99|%{$s-split"(
|..{0,$_})"-ne''-replace(' '*!$_*($s[0]-ne32)+' +$'),"`t"-join''})-notmatch'(?m)^ |\t '|sort{$_|% Le*})[0]

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

덜 골프 :

param($spacedString)

$tabed = 0..99|%{
    $spacedString `
        -split "(\n|..{0,$_})" -ne '' `
        -replace (' '*!$_*($spacedString[0]-ne32)+' +$'),"`t" `
        -join ''
}

$validated = $tabed -notmatch '(?m)^ |\t '

$sorted = $validated|sort{$_|% Length}    # sort by a Length property

@($sorted)[0]  # $shortestProgram is an element with minimal length
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.