월요일 미니 골프 # 2 : 긴 텍스트 잘림


25

Monday Mini-Golf : 매주 월요일에 게시 되는 일련의 짧은 과제입니다.

많은 웹 응용 프로그램 (특히 소셜 미디어)은 긴 텍스트를 자동으로 잘라서 앱의 서식에 맞 ​​춥니 다. 이 과제에서는 텍스트의 통과를 특정 길이로 자동 트리밍하는 알고리즘을 만듭니다.

도전

도전의 목표는 두 가지 주장을 취하는 프로그램이나 함수를 작성하는 것입니다.

  • 잘라낼 텍스트 T
  • 반환 할 최대 길이 L

그리고 다음 논리로 잘린 T를 반환합니다 .

  • T 의 길이 가 L 보다 작거나 같은 경우 절단이 필요하지 않습니다. 원래 문자열을 반환하십시오.
  • T 를 길이 L- 2로 자릅니다 . 공백이나 하이픈이 없으면 T 를 정확하게 L -3 자로 잘린 다음 줄임표로 반환하십시오 ....
  • 그렇지 않으면 결과의 끝을 마지막 공백 또는 하이픈으로 자릅니다. 줄임표를 추가 ...하고 결과를 반환하십시오.

세부

  • TL 은 임의의 형식 및 순서로 취해질 수있다.
  • 3 < L <2 31 이라고 가정 할 수 있습니다 .
  • U + 2026 가로 줄임표를 사용할 수 없습니다 . 세 개의 마침표를 사용해야합니다.
  • 공백이나 하이픈으로 입력이 시작되지 않습니다.
  • 입력에는 일반 공백 이외의 공백이 포함되지 않습니다. (탭, 줄 바꾸기 등 없음)

테스트 사례

입력 :

"This is some very long text." 25
"This-is-some-long-hyphen-separated-text." 33
"Programming Puzzles & Code Golf is a question and answer site for programming puzzle enthusiasts and code golfers." 55 
"abcdefghijklmnopqrstuvwxyz" 20
"a b c" 4
"Very long." 100

출력 :

"This is some very long..."
"This-is-some-long-hyphen..."
"Programming Puzzles & Code Golf is a question and..."
"abcdefghijklmnopq..."
"a..."
"Very long."

따옴표는 문자열임을 지정하기위한 것이므로 포함 할 필요는 없습니다.

채점

이것은 이므로 바이트 단위의 가장 짧은 유효한 코드가 이깁니다. Tiebreaker는 최종 바이트 수에 먼저 도달 한 제출에갑니다. 우승자는 다음주 10 월 5 일 월요일에 선발됩니다.

편집 : Pyth와 함께 25 바이트 로 @Jakube를 우승자에게 축하드립니다 !


7
이 과제에 대한 답변은 해당 언어의 표준 기능이어야합니다. 너무 자주 나는 나쁜 곤경을 특징으로하는 UI를 보았습니다 ...
Sanchises

1
... "그렇지 않으면 결과의 끝을 마지막 공간이나 하이픈을 포함하여"NOT "까지 자릅니다." 권리?
아나 톨릭

텍스트에 탭이 있습니까?
kirbyfan64sos

@anatolyg 아니요. 마지막 공백이나 하이픈이 줄임표 앞에 표시되기 때문입니다.
ETHproductions

안녕하십니까? 세부 사항 섹션에 추가하겠습니다.
ETHproductions

답변:


12

Pyth, 25 바이트

+WnzK<zeo}@zN" -"-Q2K"...

온라인으로 사용해보십시오 : 데모 또는 테스트 스위트

설명:

+WnzK<zeo}@zN" -"-Q2K"...  implicit: z = input string, Q = input number
        o        -Q2       order the indices N in [0, 1, ..., Q-3] by
         }@zN" -"            z[T] in " -"
                           (hyphen-indices get sorted to the back)
       e                   take the last such number
     <z                    reduce z to length ^
    K                      save this string to K
+WnzK               K"...  print (K + "...") if z != K else only K

4
나는 코드가 끝날
때가

7

펄, 69 59 52 바이트

51 바이트 코드 + 1 바이트 명령 줄 숫자 입력이 -i 매개 변수와 함께 제공 될 수 있다고 가정합니다.

s/.{$^I}\K.*//&&s/(^([^ -]*).|.*\K[ -].*)..$/$2.../

용법:

echo "This-is-some-long-hyphen-separated-text." | perl -p -i"33" entry.pl

7

파이썬 2, 78 73 바이트

t,l=input()
u=t[:l-2]
print(t,u[:max(map(u.rfind,' -'))]+'...')[l<len(t)]

입력 형식은 입력 예를 따릅니다.


1
Anarchy Golf의 친숙한 이름. 환영!
xnor

7

자바 스크립트 (ES6), 123 78 67 61 바이트

나는 이것을 많이 줄일 수있을 것으로 기대하지는 않았지만 스플 라이스 / 교체 콤보는 잘림이 필요한 모든 경우를 다룰 수 있음이 밝혀졌습니다.

(T,L)=>T[L]?T.slice(0,L-2).replace(/([ -][^ -]*|.)$/,'...'):T

첫 번째 인수는 문자열이고 두 번째 인수는 길이입니다. 길이 점검 최적화를위한 edc65 덕분에 특별 감사합니다!

원래 코드는 다음과 같습니다 (123 바이트).

(T,L)=>(T.length>L?(S=T.slice(0,L)).slice(0,(m=Math.max(S.lastIndexOf` `,S.lastIndexOf`-`))<0?L-3:Math.min(L-3,m))+'...':T)

4
영리한! +1. 팁 : 종종 .length스트링 (T,L)=>T[L]?T.slice(0,L-2).replace(/([ -][^ -]*|.)$/,'...'):T스코어 의 길이를 확인할 필요가 없습니다. 61
edc65

트윗 담아 가기 나는 길이 검사에 대한 최적화를 찾고 있었고, 그것을 줄이는 방법이 있어야한다고 생각했지만, 당신의 방법은 나에게 일어나지 않았습니다. 훌륭한 제안! : D
Mwr247

당신은 대체 할 수 [ -][^ -]\s\S할인율 5 이상의 바이트
숀 H

훌륭한 솔루션! @ShaunH, 그렇게하면 하이픈에 작동하지 않습니까?
Jarmex

@Jarmex Silly brain, 그렇습니다. 가장 확실하지 않습니다.
Shaun H

5

TI-BASIC, 87 바이트

Prompt L,Str1
For(X,1,L
{inString(Str1," ",X),inString(Str1,"-",X
max(I,max(Ans*(Ans≤L-3->I
End
Str1
If L<length(Ans
sub(Ans,1,I+(L-3)not(I))+"...
Ans

TI-BASIC에는 많은 문자열 조작 명령이 없으므로 마지막 인덱스를 수동으로 찾아야합니다. 문자열에 검색 할 문자열이 없으면 inString(0을 반환합니다. 1부터 모든 위치에서 시작하는 하이픈과 공백을 검색합니다. 에가 L, 그리고보다 적은 가장 많은 수를 기록거나 같음 L-3. 그 숫자 I가 여전히 0이면, L-3대신 종료 인덱스로 사용합니다.

계산기의 한계로 인해 문자열의 주소 지정이 가능한 최대 색인은 9999입니다. 따라서 더 큰 문자열의 경우 실패합니다.

변수 I를 0 으로 자동 초기화하는 계산기의 동작에 의존 하므로 I실행하기 전에 계산기의 메모리를 삭제 하거나 지우십시오.


목록을 사용하여 가장 큰 지수를 찾는 더 짧은 해결책이 있지만 크기 제한은 9999가 아니라 ~ 500이됩니다.
lirtosiast

4

C # .NET, 187169 바이트

흠 ...

string f(string T,int L){if(T.Length<=L)return T;T=T.Substring(0,L-2);return T.Substring(0,T.Contains(" ")||T.Contains("-")?T.LastIndexOfAny(new[]{' ','-'}):L-3)+"...";}

예, 물론 바이트를 줄이기 위해 공백을 제거했습니다.
Salah Alami

3

파이썬 2, 105 바이트

def t(s,l):a=s[:l-2];return s[:max(a.rfind(' '),a.rfind('-'))]+'...'if' 'in a or'-'in a else a[:-1]+'...'

로 전화

>>> print t("This is some very long text.", 25)
This is some very long...

1

그루비, 95 바이트

a={T,L->F=T.size()<=L?T:T[0..L-3]
m=F=~'(.*[- ])'
F==T?F:m?m[0][0].trim()+'...':F[0..-2]+'...'}

꽤 간단하고 아마도 더 골프를 칠 수 있습니다



1

T-SQL, 145 바이트

create proc a(@t varchar(max),@l int)as if LEN(@t)<=@l return @t;set @t = LEFT(@t,@l-3) select LEFT(@t,LEN(@t)-CHARINDEX('-',REVERSE(@t)))+'...'

용법:

exec a("This is some very long text.", 25) exec a("This-is-some-long-hyphen-separated-text.", 33)



1

실론 386 333 252 230 222 216 171 153 131 111

String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";

Ungolfed Original :

String truncate(String text, Integer length) {
    if(text.size < length) {
        return text;
    }
    Boolean spacePredicate(Character char) {
        return char == ' ' || char == '-';
    }
    Integer? spaceIndex = text[0:length-2].lastIndexWhere(spacePredicate);
    if(exists spaceIndex) {
        return text[0:spaceIndex] + "...";
    }
    return text[0:length-3]+"...";
}

이것은 386 바이트 / 문자입니다. 몇 가지 흥미로운 기능은 다음과 같습니다.

x[y:z]구문에 대한 문법 설탕입니다 x.measure(y, z), 그리고 부분 범위 반환 x에서 시작하는 y길이 z- 문자열,이 문자열입니다. (도있다 x[y..z]A는 문법 기간 Z에 인덱스 Y의 양단을 포함뿐만 아니라 반 개방 스팬 x[...z]하고 x[y...]).

List.lastIndexWhere술어 (즉,리스트 요소를 취하고 부울을 리턴하는 함수, 즉 여기서 a Callable<Boolean, [Character]>)를 취하고 , 술어가 이행되는 마지막리스트 요소의 색인을 제공합니다 (또는 이행되지 않은 경우 널 (NULL)). 문자열이 목록이므로 문자열에도 적용됩니다.

이것의 결과는 spaceIndextype Integer|Null이거나 Integer?짧습니다. 즉 Integer 또는 nulltype의 유일한 값일 수 Null있습니다. (이름 도 특별 spaceIndex하다는 사실을 알지 못했을 때 유래 한 것입니다. 더 좋을 것 -같습니다 breakIndex.)

exists spaceIndex우리가하면 확인할 수 있습니다 spaceIndexnull가 아닌 다음 뭔가 다른 작업을 수행. (이 if-block 내부에서 컴파일러는 null이 아닌 것을 알고 있습니다 ... 그러지 않으면 spaceIndex문자열에 액세스하는 데 불평했을 것 입니다.)

로컬 함수 대신 spacePredicate익명 함수를 사용할 수도 있습니다

(Character char) => char == ' ' || char == '-'

이것은 우리를 333 자로 만듭니다 :

String truncate(String text, Integer length) {
    if(text.size < length) {
        return text;
    }
    Integer? spaceIndex = text[0:length-2].lastIndexWhere(
        (Character char) => char == ' ' || char == '-');
    if(exists spaceIndex) {
        return text[0:spaceIndex] + "...";
    }
    return text[0:length-3]+"...";
}

다음 최적화는 더 짧은 변수 및 함수 이름을 사용하여 81 바이트에서 252로 줄입니다.

String t(String s, Integer l) {
    if(s.size < l) {
        return s;
    }
    Integer? i = s[0:l-2].lastIndexWhere(
        (Character e) => e == ' ' || e == '-');
    if(exists i) {
        return s[0:i] + "...";
    }
    return s[0:l-3]+"...";
}

술어 함수는 실제로 선언 된 인수 유형이 필요하지 않으며, 이는 컴파일러에서 유추 할 수 있습니다. 의 유형과 동일합니다 i(여전히 value선언으로 표시하기 위해 작성 해야합니다). 이제 그 선언은 한 줄에 들어가기에 충분히 짧아서 230으로 줄였습니다.

String t(String s, Integer l) {
    if(s.size < l) {
        return s;
    }
    value i = s[0:l-2].lastIndexWhere((e) => e == ' ' || e == '-');
    if(exists i) {
        return s[0:i] + "...";
    }
    return s[0:l-3]+"...";
}

대신 e == ' ' || e == '-'우리는 쓸 수도 있습니다 e in [' ', '-'](또는 e in {' ', '-'}, 이것은 튜플 대신 반복 가능한 생성자입니다). in연산자는 우리가 그 튜플의 통과 수 있다는 생각에 우리를 가져 오는 방법 Category.contains, 매핑 contains를 빼고, (그렇게 또한 문자를 받아, 물건을 복용 호출입니다) 직접 방법을 (e) => ...보일러 (222 바이트) :

String t(String s, Integer l) {
    if(s.size < l) {
        return s;
    }
    value i = s[0:l-2].lastIndexWhere([' ', '-'].contains);
    if(exists i) {
        return s[0:i] + "...";
    }
    return s[0:l-3]+"...";
}

실제로, 동일한 두 문자를 포함하는 다른 범주는 두 문자 string " -"입니다. 또한 하위 문자열도 포함되어 있지만 여기에는 아무런 영향이 없습니다. 216 바이트

String t(String s, Integer l) {
    if(s.size < l) {
        return s;
    }
    value i = s[0:l-2].lastIndexWhere(" -".contains);
    if(exists i) {
        return s[0:i] + "...";
    }
    return s[0:l-3]+"...";
}

나는 우리가, 다른 사람에의 차례를하자이 라인의 가장 밖으로있어 생각 ... 마지막 두 개의 리턴 문은 우리가 활용할 수있는 몇 가지 유사성이 - 그들은 단지 다를 il-3, 그리고 사용하는 inull가 아닌 바로 그 때를, 그렇지 않으면 l-3. 운 좋게도 이것은 else운영자를위한 것입니다!

String t(String s, Integer l) {
    if(s.size < l) {
        return s;
    }
    value i = s[0:l-2].lastIndexWhere(" -".contains);
    return s[0:(i else l-3)] + "...";
}

( else보다 우선 순위가 낮은 괄호가 필요한 것 같습니다 [:].) 171 자입니다. 이제 i한 번만 사용되므로 인라인으로 153자를 가져올 수 있습니다.

String t(String s, Integer l) {
    if(s.size < l) {
        return s;
    }
    return s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}

우리는 또한이 대체 할 수있는 if-return-return상기의 조합에 의해 조합 thenelse하나의 연산자 return. ( then첫 번째 피연산자가 true이면 return은 두 번째 피연산자이고, 그렇지 않으면 null이며, 두 번째 피연산자 else를 반환 할 수 있습니다 .`) 131 바이트

String t(String s, Integer l) {
    return s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}

표현식과 함께 하나의 리턴 만 포함하는 함수는 "뚱뚱한 화살표"표기법으로 작성하여 123을 제공 할 수 있습니다.

String t(String s, Integer l) =>
    s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";

불필요한 공백을 제거하면 최종 111 바이트가됩니다.

String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";

또한 다음은 질문에서 예제를 인쇄하는 함수입니다 ( t2 단계 후에 사용 된 이름 사용).

shared void testTruncate() {
    value testInputs = {
        ["This is some very long text.", 25],
        ["This-is-some-long-hyphen-separated-text.", 33],
        ["Programming Puzzles & Code Golf is a question and answer site for programming puzzle enthusiasts and code golfers.", 55], 
        ["abcdefghijklmnopqrstuvwxyz", 20],
        ["a b c", 4],
        ["Very long.", 100]
    };
    for(input in testInputs) {
        print(t(*input));
    }
}

1

POSIX 쉘 + GNU sed, 65 바이트

sed -re "s/(.{$1}).+/\1/;T;s/(.*)[- ]...*/\1.../;t;s/...$/.../;:"

이것은 sed를위한 일입니다! 그러나 길이 제한을 얻으려면 쉘이 필요했습니다 (아마도 Perl이 더 좋을 것입니다). sed 부분은 우리가 완료하면 조건부 점프와 함께 상당히 간단한 순서로 확장됩니다.

s/(.{$1}).+/\1/
T
s/(.*)[- ]...*/\1.../
t
s/...$/.../
:

1

Mathematica 192 바이트

t=With[{r=StringTake[#,Min[#2-2,StringLength[#]]],p={"-",Whitespace},e="..."}, 
  Which[StringLength[#]<=#2,#,StringFreeQ[r,p],StringDrop[r,-1]<>e,
   True,StringTake[r,Max[StringPosition[r,p]]-1]<>e]]&

로 호출

t["This is some very long text.", 25]

1

> <>, 74 바이트

l$-:1)?\~r05.
/?=0:~$<-1
\}:0=  ?\::"- "@=@=+?
>~"..."r\}
/!?     <
>ol?!;

이 솔루션을 사용하려면 문자열을 자르고 L 이미 스택에 있어야합니다.

정렬 문제로 인해 7 바이트가 낭비되어 여전히 골프를 치려고합니다.


1

C # (157) :

Salah Alami답변을 기반으로 하지만 더 짧습니다. 문자열 클래스에서 파생 IEnumerable<char>, 그래서 대신 T.Contains(" ")||T.Contains("-")내가 사용" -".Any(x=>T.Contains(x)) .

해결책:

string f(string T,int L){if(T.Length<=L)return T;T=T.Substring(0,L-2);return T.Substring(0," -".Any(T.Contains)?T.LastIndexOfAny(new[]{' ','-'}):L-3)+"...";}

언 골프 드 :

string f (string T, int L)
{
    if (T.Length <= L)
        return T;

    T = T.Substring(0, L - 2);

    return T.Substring(0, " -".Any(T.Contains) ? T.LastIndexOfAny(new[]{' ', '-'}) : L - 3) + "...";
}

최신 정보:

SLuck49의 의견 덕분에 Any(T.Contains)대신 6 바이트를 절약했습니다 Any(x=>T.Contains(x)).


1
들어 .Any(x=>T.Contains(x))직접 람다 대신 방법을 사용할 수 있습니다처럼 .Any(T.Contains)6 바이트 저장
SLuck49

@ SLuck49 감사합니다, 내 대답을 업데이트했습니다.
Abbas

1

GS2 , 29 바이트

이 프로그램은 표준 입력을받습니다. 첫 번째 줄은 문자열이고 두 번째 줄은 대상 길이입니다.

2a 0e 56 3c 40 a0 74 20 22 22 04 5d 2e 2a 3f 5b
20 2d 5d 7c 2e 07 2e 2e 2e 9d 20 e4 35

GS2 코드는 때때로 읽기 어려울 수 있습니다. :) 다음은 몇 가지 주석입니다.

2a         # lines - split input on newlines yielding a two element array
0e         # extract-array - pop array, push both elements 
56         # read-num - convert length string to number
3c         # take - truncate the string to specified length
40         # dup - duplicate truncated string on stack
a0         # junk1 - push the last popped value, the un-truncated string
74         # ne - test for inequality
    20     # reverse string
    22 22  # tail tail - remove first two characters

    # regex replace first occurrence of ".*?[ -]|." with "..."
    04 5d 2e 2a 3f 5b 20 2d 5d 7c 2e 07 2e 2e 2e 9d 

    20     # reverse string
e4         # block5 - make a block out of last 5 instructions
35         # when - conditionally execute block

1

그루비, 56 바이트

Kleyguerth의 답변을 먼저 복사 했으므로 동일한 변수 이름이 ...

문자열을 2 문자로 자른 다음 대부분의 작업은 정규식에 의해 수행되고 대시 또는 공백을 대체하고 대시 또는 공백이 아닌 문자 수를 "."로 바꿉니다. 또는 문자열 앞의 모든 문자가 대시 또는 "."가있는 공백이 아닌 경우 문자열 끝에있는 문자를 바꾸십시오. 정규식을 쓰는 것보다 단어를 쓰는 것이 더 어렵습니다 ...

a={T,L->T.size()<=L?T:T[0..L-3].replaceAll("([- ][^ -]*|(?<=[^- ]*).)\$",".")+".."}

편집 : 실제로, 정규 표현식과 일치하는 문자열 부분을 제거하고 끝에 "..."를 추가 할 수 있습니다.

a={T,L->T.size()<=L?T:T[0..L-3]-~/[- ][^ -]*$|.$/+"..."}



당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.