각 문자로 시작하는 첫 단어를 찾으십시오


25

문자열이 주어지면 각 문자로 시작하는 첫 번째 단어를 찾으십시오 (대소 문자 구분).

견본

Ferulas flourish in gorgeous gardens.입력으로 사용 :

"Ferulas flourish in gorgeous gardens."
 ^^^^^^^          ^^ ^^^^^^^^
 |                |  |
 |                |  --> is the first word starting with `g`
 |                --> is the first word starting with `i`
 --> is the first word starting with `f`

그런 다음이 샘플의 출력은 단일 공백으로 결합 된 일치하는 단어 여야합니다.

"Ferulas in gorgeous"

도전

입력과 출력 모두 문자열 표현이거나 언어에서 가장 가까운 대안이어야합니다.

프로그램 또는 기능이 허용됩니다.

단어 중 하나 이상을 고려할 수 있습니다 lowercase or uppercase letters, digits, underscore.

이것은 이며 바이트 단위로 가장 짧은 답변입니다.

다른 샘플들 :

input: "Take all first words for each letter... this is a test"
output: "Take all first words each letter is"

input: "Look ^_^ .... There are 3 little dogs :)"
output: "Look _ There are 3 dogs"

input: "...maybe some day 1 plus 2 plus 20 could result in 3"
output: "maybe some day 1 plus 2 could result in 3"

후행 / 시작 공간이 허용됩니까? <s> 원래 문자열에서 단어가 한
칸씩

예제에서 이해 했으므로 주석에 <s> </ s>가 있습니다. 공간 정리는 어떻습니까?
Qwertiy

답변:


17

레티 나 , 28 바이트 :

M! i` \ b (\ w) (? <! \ b \ 1. +) \ w *
¶
 
  • M! -각 작품을 일치시키고 개행으로 구분 된 모든 단어를 인쇄하십시오.
  • i -사건을 무시하십시오.
  • \b(\w) -각 단어의 첫 글자를 캡처
  • (?<!\b\1.+)-글자를 일치시킨 후 같은 글자로 시작하는 이전 단어가 없는지 확인하십시오. \1.+두 글자 이상을 보장하므로 현재 단어를 건너 뜁니다.
  • \w*-나머지 단어와 일치시킵니다.
    위의 단어는 단어와 만 일치하며 다른 모든 문자는 제거됩니다.
  • ¶\n -줄 바꿈을 공백으로 바꿉니다.

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


9

망막 , 45 바이트

i` \ b ((\ w) \ w *) \ b (? <= \ b \ 2 \ w * \ b. +)

\ W +
 
^ | $

단일 정규 표현식을 사용하여 동일한 \w문자로 시작하는 이후 단어를 제거하고 (대소 문자를 구분하지 않는 i옵션) 런을 \W단일 공백으로 변환 한 다음 결과에서 선행 / 트레일 공백을 제거합니다.

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

편집 : 더 짧은 버전 은 @ Kobi의 답변 을 참조하십시오.M!`


젠장, 간신히 날 이겼어! 그래도 룩을 알아낼 수 없었습니다.
GamrCorps

3
나는 다른 망막 대답을 추가 한 - 내가 생각하는 서로 다른 정도가 (기본 개념은 물론, 유사합니다) 경우 그 확인을합니다.
Kobi

1
@Kobi 훨씬 나아 졌기 때문에 기쁘다. :) Retina의 회선 옵션에 대해 얼마나 많이 배워야하는지, 그렇지 않은 것이 무엇인지 깨닫게한다.
Sp3000

몇 바이트를 절약하기 위해 이것을 할 수 있습니까? i` \b((\w)\w*)\b(?<=\b\2\w*\b.+)(첫 번째 앞의 공백 \b) 나중에 줄이 필요하지 않습니까?
Leaky Nun

@KennyLau 불행히도, 단어가 반드시 공백으로 분리 될 필요가 없기 때문에 작동한다고 생각하지 않습니다. 예 :a...a -> a
Sp3000

9

자바 스크립트 (ES6), 73 71 바이트

s=>s.match(u=/\w+/g).filter(w=>u[n=parseInt(w[0],36)]?0:u[n]=1).join` `

@ edc65 덕분에 2 바이트를 절약했습니다!

테스트

var solution = s=>s.match(u=/\w+/g).filter(w=>u[n=parseInt(w[0],36)]?0:u[n]=1).join` `;
var testCases = [
  "Ferulas flourish in gorgeous gardens.",
  "Take all first words for each letter... this is a test",
  "Look ^_^ .... There are 3 little dogs :)",
  "...maybe some day 1 plus 2 plus 20 could result in 3"
];
document.write("<pre>"+testCases.map(t=>t+"\n"+solution(t)).join("\n\n")+"</pre>");


사용 parseInt("_",36) = NaN? 신성 모독!
Sp3000

1
재미있는 사실은 : 그것은 SP3000 @ 작동
edc65

u = regexp를 사용하는 것은 정말 영리합니다. 2 바이트 저장s=>s.match(u=/\w+/g).filter(w=>u[w=parseInt(w[0],36)]?0:u[w]=1).join' '
edc65

@ edc65 감사합니다. 단일 36 자리 숫자에 대해 37 개의 가능한 출력이 있다는 것이 실제로 매우 편리합니다.
user81655

7

Pyth, 23 바이트

J:z"\w+"1jdxDJhM.grhk0J

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

J:z"\w+"1정규식을 사용하여 입력에서 모든 단어를 찾아서에 \w+저장합니다 J.

.grhk0J단어를 소문자 첫 글자로 hM그룹화하고 각 그룹에서 첫 번째 문자를 가져 와서 xDJ입력 문자열에서 해당 단어를 색인별로 정렬 한 후 jd공백을 넣습니다.


4

펄 6, 39 바이트

{.words.grep({!%.{.substr(0,1).lc}++})}

1
일치하는 단어를 수정하고 부분을 \w+골프화하는 42 바이트substr
Jo King

3

C, 142 (132) 122 바이트

@tucuxi 덕분에 10 바이트 가벼워졌습니다!

b[200],k;main(c){for(;~c;isalnum(c)|c==95?k&2?:(k|=!b[c|32]++?k&1?putchar(32):0,7:2),k&4?putchar(c):0:(k&=1))c=getchar();}

마지막 출력 단어 다음에 후행 공백을 인쇄합니다.


1
당신을위한 검사를 면도 할 수 c>47c<58사용하여 isalnum대신isalpha
투 쿠시

3

MATL , 23 바이트

'\w+'XXtck1Z)t!=XRa~)Zc

이것은 Jakube가 불필요한 문자를 제거하고 동시에 나누기 위해 정규 표현식을 사용 한다는 아이디어 를 빌려 줍니다 .

입력은 작은 따옴표로 묶인 문자열입니다.

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

설명

'\w+'XX  % find words that match this regexp. Gives a cell array
t        % duplicate
c        % convert into 2D char array, right-padded with spaces
k        % make lowercase
1Z)      % get first column (starting letter of each word)
t!=      % duplicate, transpose, test for equality: all combinations  
XR       % set diagonal and below to 0
a~       % true for columns that contain all zeros       
)        % use as a logical index (filter) of words to keep from the original cell array
Zc       % join those words by spaces

2

Vim 57 키 스트로크

:s/[^a-zA-Z_ ]//g<cr>A <cr>ylwv$:s/\%V\c<c-v><c-r>"\h* //eg<c-v><cr>@q<esc>0"qDk@q

설명:

:s/[^a-zA-Z_ ]//g                                 #Remove all invalid chars.
A <cr>                                            #Enter insert mode, and enter 
                                                  #a space and a newline at the end
ylwv$:s/\\c%V<c-v><c-r>"\h* //eg<c-v><cr>@q<esc>  #Enter all of this text on the 
                                                  #next line

0                                                 #Go to the beginning of the line
"qD                                               #Delete this line into register
                                                  #"q"
k@q                                               #Run "q" as a macro  

#Macro
ylw                                               #Yank a single letter
   v$                                             #Visual selection to end of line
     :s/                                          #Substitute regex
       \%V\c                                      #Only apply to the selection and 
                                                  #ignore case
            <c-v><c-r>"                           #Enter the yanked letter
                       \h*                        #All "Head of word" chars
                                                  #And a space
                           //                     #Replace with an empty string
                             eg                   #Continue the macro if not found
                                                  #Apply to all matches
                               <c-v><cr>          #Enter a <CR> literal
                                        @q<esc>   #Recursively call the macro

나는 이것이 얼마나 오랫동안 정말로 실망했다. "잘못된"문자 (모든하지만 a-z, A-Z, _정말 저리 던져 버리고 공간). 이 작업을 수행하는 더 좋은 방법이 있다고 확신합니다.

:s/[^a-zA-Z_ ]//g

\h공간에 대한 모든 기대와 일치 하기 때문에 메타 문자를 범위에 넣는 방법을 알 수 없습니다. 누군가 팁이 있다면, 나는 그것을 듣고 싶습니다.


3
a-zA-Z_안돼 \w? 자릿수는 유효합니다
edc65

2

줄리아 165 155 151 129 102 바이트

g(s,d=[])=join(filter(i->i!=0,[(c=lcfirst(w)[1])∈d?0:(d=[d;c];w)for w=split(s,r"\W",keep=1<0)])," ")

문자열을 받아들이고 문자열을 반환하는 함수입니다.

언 골프 드 :

function g(s, d=[])
    # Split the string into an array on unwanted characters, then for
    # each word, if the first letter has been encountered, populate
    # this element of the array with 0, otherwise note the first letter
    # and use the word. This results in an array of words and zeros.
    x = [(c = lcfirst(w)[1])  d ? 0 : (d = [d; c]; w) for w = split(s, r"\W", keep=1<0)]

    # Remove the zeros, keeping only the words. Note that this works
    # even if the word is the string "0" since 0 != "0".
    z = filter(i -> i != 0, x)

    # Join into a string and return
    return join(z, " ")
end

Sp3000의 도움으로 53 바이트를 절약했습니다!



2

C # (LINQPAD) - 136 128 바이트

var w=Util.ReadLine().Split(' ');string.Join(" ",w.Select(s=>w.First(f=>Regex.IsMatch(""+f[0],"(?i)"+s[0]))).Distinct()).Dump();

2

05AB1E , 40 바이트

암호:

94L32+çJžj-DU-ð¡""Kvy¬Xsl©åï>iX®«Uy}\}ðý

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

설명:

먼저 94L32+ç( Try here )를 사용하여 입력 문자열에서 삭제해야하는 모든 문자를 생성합니다 . 우리는이 사용하는 문자열에 가입 J하고 제거 [a-zA-Z0-9_](ZJ에 저장되어 여기에 시도를 ). 첫 번째 문자열에서 두 번째 문자열에있는 모든 문자를 제거하면 다음과 같이됩니다.

!"#$%&'()*+,-./:;<=>?@[\]^`{|}~

여기 에서도 테스트 할 수 있습니다 . 우리는 D이것을 복제 X하고 U-command 와 함께 저장 합니다 . 그런 다음이 문자열에있는 모든 문자를 입력에서 제거합니다. 그런 다음 공백을 사용하여 공백으로 나누고 ð¡빈 문자열을 모두 제거합니다 (을 사용하여 ""K). 우리는 지금 이것을 가지고 있습니다 .

이것은 우리가 작업 할 깨끗한 버전의 입력입니다. 를 사용하여 각 요소를 매핑 v합니다. 이것은 y문자열 변수로 사용 됩니다. 우리는 사용하여 문자열의 첫 번째 문자 취 ¬푸시 X모두 포함 된 문자열이 들어, 금지 문자를 ( !"#$%&'()*+,-./:;<=>?@[\]^`{|}~). 우리 l는 첫 번째 문자 의 소문자 버전 ( ©레지스터로 도 선택 될 것임)이이 문자열을 사용하여이 문자열에 있는지 확인합니다 å. 이 부분에서 다루는 내용 : ï>i, 첫 번째 문자가 금지 된 문자 문자열 ( X) 에 없으면 이 문자를 금지 된 문자 목록에 추가하고 (으로 완료 X®«U) y스택 맨 위로 밉 니다.

마지막으로 문자열이 필터링되면 스택을 공백으로 묶습니다 ðý.


1
... 설명? :-)
Luis Mendo

@LuisMendo 저를 상기시켜 주셔서 감사합니다! 완료 :)
Adnan

2

PHP

대부분의 답변에서 정규 표현식을 사용하여 영감을 얻은 결과 원래 깔끔한 변형을 보여주기 위해 정규 표현식을 전혀 사용하지 않고이 작업을 시도했지만 입력으로 깨끗한 문자열을 사용하지 않는 문제는 그 아이디어를 망쳤습니다. 슬퍼.

함수 래퍼 (89 바이트)

function f($s){foreach(preg_split('/\W/',$s)as$w)$c[lcfirst($w)[0]]++?:$v.=" $w";echo$v;}

함수 래퍼가없는 경우 (미리 선언 된 $ s, 73 바이트)

foreach(preg_split('/\W/',$s)as$w)$c[lcfirst($w)[0]]++?:$v.=" $w";echo$v;

설명:

foreach(preg_split('/\W/',$s)as$w)$c[lcfirst($w)[0]]++?:$v.=" $w";echo$v;
        preg_split('/\w/',$s)                                             Break input on all non-word characters
foreach(                     as$w)                                        Loop through each 'word'
                                     lcfirst($w)[0]                       Take the first letter of the lowercase version of the word
                                  $c[              ]++?:                  Increment an array element with a key of that letter after checking if it's false-y (0)
                                                        $v.=" $w";        Add the word if the letter wasn't found (if the previous condition evaluated to false)
                                                                  echo$v; Print the new string to screen.

유감스럽게도 편지를 확인 / 변환하는 더 빠른 방법을 찾을 수 없다는 것이 유감입니다.


2

파이썬, 103 바이트

import re
lambda s,d=[]:[w for w in re.findall("\w+",s)if(d.append(w.lower()[0])or d[-1])not in d[:-1]]

1

루아, 172 바이트

내가 원했던 것보다 길어졌습니다 ...

t={}(...):gsub("[%w_]+",function(w)b=nil for i=1,#t
do b=t[i]:sub(1,1):lower()==w:sub(1,1):lower()and 1 or b
end t[#t+1]=not b and w or nil end)print(table.concat(t," "))

언 골프

t={}                           -- initialise the accepted words list
(...):gsub("[%w_]+",function(w)-- iterate over each group of alphanumericals and underscores
  b=nil                        -- initialise b (boolean->do we have this letter or not)
  for i=1,#t                   -- iterate over t
  do
    b=t[i]:sub(1,1):lower()    -- compare the first char of t's i word
       ==w:sub(1,1):lower()    -- and the first char of the current word
           and 1               -- if they are equals, set b to 1
           or b                -- else, don't change it
  end
  t[#t+1]=not b and w or nil   -- insert w into t if b isn't set
end)

print(table.concat(t," "))     -- print the content of t separated by spaces

1

진지하게, 43 바이트

6╙¬▀'_+,;)-@s`;0@Eùk`M┬i;╗;lrZ`i@╜í=`M@░' j

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

정규 표현식 기능이 없기 때문에 필요한 것보다 훨씬 어렵습니다.

설명:

6╙¬▀'_+,;)-@s`;0@Eùk`M┬i;╗;lrZ`i@╜í=`M@░' j
6╙¬▀                                         push digits in base 62 (uppercase and lowercase letters and numbers)
    '_+                                      prepend underscore
       ,;)                                   push two copies of input, move one to bottom of stack
          -                                  get all characters in input that are not letters, numbers, or underscores
           @s                                split input on all occurrences of non-word characters
             `;0@Eùk`M                       for each word: push the first letter (lowercased)
                      ┬i                     transpose and flatten (TOS is list of first letters, then list of words)
                        ;╗                   push a copy of the first letters list to register 0
                          ;lrZ               zip the list of first letters with their positions in the list
                              `i@╜í=`M       for each first letter: push 1 if that is the first time the letter has been encountered (first index of the letter matches its own index) else 0
                                      @░     filter words (take words where corresponding element in the previous list is truthy)
                                        ' j  join on spaces

1

루비 76 바이트

s;f={};s.scan(/(([\w])[\w]*)/).map{|h,i|f[j=i.upcase]?nil:(f[j]=!p; h)}.compact.*' '

또는 메서드 정의가 88 바이트 인 경우

def m s;f={};(s.scan(/((\w)\w*)/).map{|h,i|f[j=i.upcase]?nil:(f[j]=1; h)}-[p]).*' ';end

언 골프 및 단위 테스트 :

def m_long(s)
  #found  - Hash with already found initials
  f={}
  #h=hit, i=initial, j=i[0].downcase
  s.scan(/(([\w\d])[\w\d]*)/).map{|h,i| 
    f[j=i.upcase] ? nil : (f[j] = true; h)
  }.compact.join(' ')
end
#true == !p
#~ def m(s)
  #~ f={};s.scan(/(([\w\d])[\w\d]*)/).map{|h,i|f[j=i.upcase]?nil:(f[j]=!p; h)}.compact.join' '
#~ end
def m s;f={};s.scan(/(([\w\d])[\w\d]*)/).map{|h,i|f[j=i.upcase]?nil:(f[j]=!p; h)}.compact.join' ';end

#~ s = "Ferulas flourish in gorgeous gardens."
#~ p s.split

require 'minitest/autorun'
class FirstLetterTest < Minitest::Test
  def test_1
    assert_equal("Ferulas in gorgeous",m("Ferulas flourish in gorgeous gardens."))
    assert_equal("Ferulas in gorgeous",m_long("Ferulas flourish in gorgeous gardens."))
  end
  def test_2
    assert_equal("Take all first words each letter is",m("Take all first words for each letter... this is a test"))
    assert_equal("Take all first words each letter is",m_long("Take all first words for each letter... this is a test"))
  end
  def test_3
    assert_equal("Look _ There are 3 dogs",m("Look ^_^ .... There are 3 little dogs :)"))
    assert_equal("Look _ There are 3 dogs",m_long("Look ^_^ .... There are 3 little dogs :)"))
  end
  def test_4
    assert_equal("maybe some day 1 plus 2 could result in 3",m("...maybe some day 1 plus 2 plus 20 could result in 3"))
    assert_equal("maybe some day 1 plus 2 could result in 3",m_long("...maybe some day 1 plus 2 plus 20 could result in 3"))
  end
end

정규식에서 \w숫자를 포함하므로 [\w\d]로 대체 할 수 있습니다 \w. 또한 nil호출 할 때 값이 배열에 join' '있거나 더 나은 *' '바이트를 절약하는 데 사용할 수있는 축약 형 인 경우 값이 사라지면 호출 compact이 필요하지 않습니다.
Value Ink

@KevinLau 감사합니다. 은 \w\d나를 당황한다. 그러나 내가 제거하면 compact추가 공간이 생깁니다 (참조 ['x',nil,'x']*'y' == 'xyyx'). 아니면 내가 뭔가를 그리워 했습니까?
knut

당신이 맞아요. 이 경우 (list-[p])바이트를 저장합니다 list.compact. 또한와 /\w/같습니다 /[\w]/. 마지막으로, 당신은 당신을 대체 할 수 nilp!p1(당신의 해시 만에 truthy 값을 필요로하기 때문에)
값 잉크

덕분에, 나는의 교체 귀하의 발언을 추가 nil로가 p작동하지 않습니다. 내 코드에서 사용하면 구문 오류가 발생합니다. 나는 캡슐화해야 (p)하지만 다시 3 문자가 있습니다.
knut

삼항을 뒤집은 다음 바이트를 저장합니다 !f[j=i.upcase]?(f[j]=1;h):p. 또한 이것을 생각했지만 문자열 색인으로 인해 작업 을 선호 s.scan(/\w+/)하고 제거합니다 . ih[0]
Value Ink

1

grep and awk, 68 56 바이트

스크립트 :

echo `grep -o '\w*'|awk '!x[tolower(substr($0,1,1))]++'`

설명:

  • grep -o 합법적 인 단어와 일치하여 각 줄에 인쇄합니다.

  • awk로 각 줄의 첫 번째 문자를 가져 와서 substr소문자로 만든 다음 해당 키로 해시 테이블 항목을 증가시킵니다. 증분 전에 값을 설정하지 않으면 줄이 인쇄됩니다.

  • echo ... 줄을 다시 단어로 바꿉니다.

나는 이전없이 솔루션을 만들려고 awk사용하여, uniq, sort, grepbash 하지만, 단지 짧은 떨어졌다. 편집 내역.

내가 놓친 개선 사항에 대해 Dennis에게 감사드립니다.


0

파이썬 3.5, 138 바이트 :

import re;lambda o,t=[]:''.join([y[0]for y in[(u+' ',t.append(u[0].lower()))for u in re.sub('\W+',' ',o).split()if u[0].lower()not in t]])

기본적으로 무슨 일이 일어나고 있는지 ..

  1. 간단한 정규식을 사용하여 프로그램은 주어진 문자열에서 소문자 또는 대문자, 숫자 또는 밑줄을 제외한 모든 문자를 공백으로 바꾼 다음 해당 공백에서 문자열을 분할합니다.
  2. 그런 다음 목록 이해를 사용하여 분할 문자열의 모든 단어를 반복하는 목록을 작성하고 각 단어의 첫 글자를 추가하여 "t"를 나열하십시오.
  3. 이 과정에서 현재 단어의 첫 글자가 목록 "t"에없는 경우 해당 단어와 후행 공백이 작성중인 현재 목록에 추가됩니다. 그렇지 않으면, 목록은 "t"를 나열하기 위해 각 단어의 첫 글자를 계속 추가합니다.
  4. 마지막으로 분할의 모든 단어가 반복되면 새 목록의 단어가 문자열로 결합되어 반환됩니다.

0

PHP 120 바이트

function a($s){foreach(preg_split('/\W/',$s)as$w)if(!$o[ucfirst($w[0])]){$o[ucfirst($w[0])]=$w;}return implode(" ",$o);}

이것은 많은 경고를 발생 시키지만 괜찮습니다.


인가 function필요?
AL

0

자바 ES6, 108 개 107 문자

107 자, 결과 문자열이 잘림

r=s=>s.split``.reverse().join``
f=s=>r(r(s).replace(/\b\w*(\w)\b(?=.*\1\b)/gi,'')).replace(/\W+/g,' ').trim()

테스트:

["Take all first words for each letter... this is a test",
"Look ^_^ .... There are 3 little dogs :)",
"...maybe some day 1 plus 2 plus 20 could result in 3"
].map(f) + '' == [
"Take all first words each letter is",
"Look _ There are 3 dogs",
"maybe some day 1 plus 2 could result in 3"
]


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