Tìm từ đầu tiên bắt đầu bằng mỗi chữ cái


25

Đưa ra một chuỗi, tìm từ đầu tiên bắt đầu bằng mỗi chữ cái (không phân biệt chữ hoa chữ thường).

Mẫu vật

Sử dụng Ferulas flourish in gorgeous gardens.làm đầu vào:

"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`

Sau đó, đầu ra cho mẫu này phải là các từ phù hợp được nối bởi một khoảng trắng:

"Ferulas in gorgeous"

Thử thách

Cả đầu vào và đầu ra phải là một đại diện chuỗi hoặc thay thế gần nhất trong ngôn ngữ của bạn.

Chương trình hoặc chức năng được phép.

Bạn có thể xem xét một từ ít nhất là một trong số : lowercase or uppercase letters, digits, underscore.

Đây là , câu trả lời ngắn nhất trong byte thắng.

Một mẫu khác:

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"

Được dấu / không gian bắt đầu được phép? <s> Tôi có thể giả sử các từ được phân tách bằng một khoảng
trắng

Tôi hiểu nó từ các ví dụ, vì vậy có <s> </ s> trong bình luận. Còn không gian cắt tỉa thì sao?
Qwertiy

Câu trả lời:


17

Võng mạc , 28 byte:

M! I` \ b (\ w) (? <! \ B \ 1. +) \ W *
¶
 
  • M! - Ghép từng tác phẩm và in tất cả các từ cách nhau bởi dòng mới.
  • i - Bỏ qua trường hợp.
  • \b(\w) - Nắm bắt chữ cái đầu tiên của mỗi từ
  • (?<!\b\1.+)- Sau khi khớp chữ cái, kiểm tra xem có từ nào trước đó bắt đầu bằng cùng một chữ cái không. \1.+đảm bảo ít nhất hai ký tự, vì vậy chúng tôi đang bỏ qua từ hiện tại.
  • \w*- phù hợp với phần còn lại của từ.
    Các từ trên chỉ khớp với các từ - tất cả các ký tự khác được loại bỏ.
  • ¶\n - Thay thế dòng mới bằng dấu cách.

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


9

Võng mạc , 45 byte

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

\ W +
 
^ | $

Chỉ cần sử dụng một biểu thức chính để loại bỏ các từ sau bắt đầu bằng cùng một \wký tự (không phân biệt chữ hoa chữ thường với itùy chọn), chuyển đổi các lần chạy \Wthành một khoảng trắng, sau đó xóa bất kỳ khoảng trắng đầu / cuối nào khỏi kết quả.

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

Chỉnh sửa: Xem câu trả lời của @ Kobi cho phiên bản ngắn hơn bằng cách sử dụngM!`


Chết tiệt, hầu như không đánh bại tôi! Tôi không thể tìm ra cái nhìn mặc dù.
GamrCorps

3
Tôi đã thêm một câu trả lời Retina khác - Tôi nghĩ rằng nó ổn nếu chúng đủ khác nhau (tất nhiên khái niệm cơ bản là tương tự).
Kobi

1
@Kobi Nó tốt hơn nhiều, vì vậy tôi rất vui khi thấy nó :) Làm cho tôi nhận ra mình cần học thêm bao nhiêu về các tùy chọn dòng của Retina và những gì không.
Sp3000

Bạn có thể làm điều này để tiết kiệm một vài byte? i` \b((\w)\w*)\b(?<=\b\2\w*\b.+)(một khoảng trắng trước đầu tiên \b) Các dòng sau đó có cần thiết không?
Leaky Nun

@KennyLau Thật không may, tôi không nghĩ rằng tác phẩm đó vì những lời không nhất thiết phải tách bằng dấu cách, ví dụ nhưa...a -> a
Sp3000

9

JavaScript (ES6), 73 71 byte

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

Đã lưu 2 byte nhờ @ edc65!

Kiểm tra

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


Sử dụng parseInt("_",36) = NaN? Lộng ngôn!
Sp3000

1
Sự thật thú vị là: nó hoạt động @ Sp3000
edc65

Sử dụng u = regapi là thực sự thông minh. Lưu 2 bytes=>s.match(u=/\w+/g).filter(w=>u[w=parseInt(w[0],36)]?0:u[w]=1).join' '
edc65

@ edc65 Cảm ơn. Thật sự khá thuận tiện khi có 37 đầu ra có thể cho một chữ số cơ sở 36.
dùng81655

7

Bình thường, 23 byte

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

Dùng thử trực tuyến: Trình diễn hoặc Test Suite

J:z"\w+"1tìm tất cả các từ trong đầu vào bằng regex \w+và lưu chúng vào J.

.grhk0Jnhóm các từ bằng chữ cái đầu tiên viết thường của chúng, hMlấy từ đầu tiên từ mỗi nhóm, xDJsắp xếp các từ này theo chỉ mục của chúng trong chuỗi đầu vào và jdđặt khoảng trắng giữa chúng.


4

Perl 6, 39 byte

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

1
42 byte giúp sửa các từ phải khớp \w+và đánh gôn substrphần
Jo King

3

C, 142 132 122 byte

Nhẹ hơn 10 byte nhờ @tucuxi!

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

In một dấu cách sau từ đầu ra cuối cùng.


1
bạn có thể cạo séc cho c>47c<58bằng cách sử dụng isalnumthay vìisalpha
tucuxi

3

MATL , 23 byte

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

Điều này mượn ý tưởng của Jakube về việc sử dụng một biểu thức chính quy để loại bỏ các ký tự không mong muốn và chia tách cùng một lúc.

Đầu vào là một chuỗi được bao quanh bởi dấu ngoặc đơn.

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

Giải trình

'\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

Tổ hợp phím 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

Giải trình:

: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

Tôi thực sự thất vọng bởi cái này dài bao nhiêu. Các ký tự "Không hợp lệ" (mọi thứ a-z, nhưng A-Z, _và không gian) thực sự đã ném tôi đi. Tôi chắc chắn có một cách tốt hơn để làm điều này:

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

\hphù hợp với tất cả những gì mong đợi về không gian, nhưng tôi không thể tìm ra cách đặt metachar trong phạm vi. Nếu ai có lời khuyên, tôi rất muốn nghe em.


3
Tại sao a-zA-Z_và không \w? chữ số hợp lệ
edc65

2

Julia, 165 155 151 129 102 byte

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)])," ")

Đây là một hàm chấp nhận một chuỗi và trả về một chuỗi.

Ung dung:

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

Đã lưu 53 byte với sự trợ giúp từ Sp3000!



2

C # (LINQPAD) - 136 128 byte

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 byte

Mã số:

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

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

Giải trình:

Trước tiên chúng tôi tạo tất cả các ký tự sẽ bị xóa khỏi chuỗi đầu vào bằng cách sử dụng 94L32+ç( Thử tại đây ). Chúng tôi tham gia chuỗi này bằng cách sử dụng Jvà loại bỏ [a-zA-Z0-9_]được lưu trữ trong žj ( Thử tại đây ). Chúng tôi xóa tất cả các ký tự trong chuỗi thứ hai khỏi chuỗi thứ nhất, sẽ để lại cho chúng tôi:

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

Điều đó cũng có thể được thử nghiệm ở đây . Chúng tôi nâng cao Dđiều này và lưu trữ Xvới U-command. Sau đó chúng tôi xóa tất cả các ký tự trong chuỗi này khỏi đầu vào. Sau đó chúng tôi phân chia trên các khoảng trắng bằng cách sử dụng ð¡và xóa tất cả các chuỗi trống (sử dụng ""K). Bây giờ chúng ta có cái này .

Đây là phiên bản sạch của đầu vào, mà chúng ta sẽ làm việc với. Chúng tôi ánh xạ qua từng yếu tố bằng cách sử dụng v. Điều này sử dụng ynhư là biến chuỗi. Chúng tôi lấy ký tự đầu tiên của chuỗi bằng cách sử dụng ¬và đẩy X, trong đó chứa một chuỗi có tất cả các ký tự bị cấm ( !"#$%&'()*+,-./:;<=>?@[\]^`{|}~). Chúng tôi kiểm tra xem lphiên bản owercase của ký tự đầu tiên, (cũng sẽ được ©phản đối với thanh ghi), có trong chuỗi này bằng cách sử dụng å. Được bao phủ bởi phần này : ï>i, nếu chữ cái đầu tiên không tồn tại trong chuỗi ký tự bị cấm ( X), chúng tôi sẽ thêm chữ cái này vào danh sách các ký tự bị cấm (thực hiện với X®«U) và chúng tôi đẩy ylên trên cùng của ngăn xếp.

Cuối cùng, khi các chuỗi được lọc, chúng ta tham gia ngăn xếp theo khoảng trắng với ðý.


1
... giải trình? :-)
Luis Mendo

@LuisMendo Cảm ơn đã nhắc nhở tôi! Xong :)
Adnan

2

PHP

Lấy cảm hứng từ việc sử dụng regex trong hầu hết các câu trả lời, ban đầu tôi đã cố gắng thực hiện điều này mà không sử dụng regex chỉ để thể hiện một biến thể gọn gàng, nhưng quan điểm không có chuỗi sạch như đầu vào đã phá hỏng ý tưởng đó. Buồn.

Với trình bao bọc hàm, 89 byte

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

Không có trình bao bọc hàm (cần $ s khai báo trước), 73 byte

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

Giải trình:

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.

Điều hối tiếc duy nhất của tôi là tôi không thể tìm thấy một cách nhanh hơn để kiểm tra / chuyển đổi trường hợp thư.


2

Python, 103 byte

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

Lua, 172 byte

Nó đã kết thúc lâu hơn mà tôi muốn ...

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," "))

Bị đánh cắp

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

Nghiêm túc, 43 byte

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

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

Việc thiếu khả năng regex khiến việc này trở nên khó khăn hơn nhiều so với mức cần thiết.

Giải trình:

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

Ruby 76 byte

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

Hoặc với định nghĩa phương thức 88 byte

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

Ungolfed và với bài kiểm tra đơn vị:

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

Trong Regex, \wbao gồm các ký tự số, vì vậy [\w\d]có thể được thay thế bằng \w. Ngoài ra, nếu nilcác giá trị nằm trong một mảng khi bạn gọi join' '(hoặc tốt hơn, *' 'là một tốc ký bạn có thể sử dụng để lưu nhiều byte hơn), chúng sẽ biến mất, vì vậy cuộc gọi đến compactlà không cần thiết.
Mực giá trị

@KevinLau Cảm ơn. Thật \w\dlà xấu hổ cho tôi. Nhưng nếu tôi loại bỏ compacttôi sẽ có thêm khoảng trắng, (xem ['x',nil,'x']*'y' == 'xyyx'). Hay tôi đã bỏ lỡ điều gì?
knut

Rất tiếc, bạn đã đúng. Trong trường hợp đó, (list-[p])lưu byte qua list.compact. Ngoài ra, /\w/tương đương với /[\w]/. Cuối cùng, bạn có thể thay thế nilbằng p!pbằng 1(vì hàm băm của bạn chỉ cần các giá trị trung thực trong đó)
Giá trị mực

Cảm ơn, tôi đã thêm nhận xét của bạn, Việc thay thế nilbằng pkhông hoạt động. Nếu tôi sử dụng nó trong mã của tôi, tôi gặp lỗi cú pháp. Tôi phải gói gọn như thế (p)- nhưng sau đó tôi lại có 3 ký tự.
knut

Lật ternary và sau đó nó hoạt động để lưu một byte : !f[j=i.upcase]?(f[j]=1;h):p. Cũng chỉ nghĩ về điều này, nhưng vì lập chỉ mục chuỗi, sử dụng s.scan(/\w+/)và loại bỏ các ilợi ích của h[0]công việc quá.
Mực giá trị

1

grep và awk, 68 56 byte

Kịch bản:

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

Giải trình:

  • grep -o khớp với các từ hợp pháp, in mỗi dòng trên dòng riêng của nó.

  • awklấy chữ cái đầu tiên của mỗi dòng substr, làm cho nó viết thường và sau đó tăng một mục có thể băm với khóa đó. Nếu giá trị không được đặt trước khi tăng, dòng được in.

  • echo ... biến các dòng trở lại thành từ

Tôi trước đây đã cố gắng để tạo ra một giải pháp mà không awksử dụng uniq, sort, grepbashnhưng giảm chỉ ngắn. Lịch sử trong các chỉnh sửa.

Cảm ơn Dennis cho một số cải tiến tôi đã bỏ lỡ.


0

Python 3.5, 138 byte:

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

Về cơ bản, những gì đang xảy ra là ..

  1. Sử dụng một biểu thức chính quy đơn giản, chương trình thay thế tất cả các ký tự, ngoại trừ chữ thường hoặc chữ in hoa, chữ số hoặc dấu gạch dưới trong chuỗi đã cho bằng khoảng trắng, sau đó tách chuỗi ở các khoảng trắng đó.
  2. Sau đó, bằng cách sử dụng tính năng hiểu danh sách, tạo một danh sách lặp qua tất cả các từ trong chuỗi phân tách và thêm các chữ cái đầu tiên của mỗi từ vào danh sách "t".
  3. Trong quá trình, nếu chữ cái đầu tiên của từ hiện tại KHÔNG có trong danh sách "t", thì từ đó và khoảng trắng ở cuối được thêm vào danh sách hiện tại sẽ được tạo. Mặt khác, danh sách tiếp tục nối các chữ cái đầu tiên của mỗi từ vào danh sách "t".
  4. Cuối cùng, khi tất cả các từ trong phần tách được lặp qua, các từ trong danh sách mới được nối thành một chuỗi và được trả về.

0

PHP 120byte

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

Điều này tạo ra một loạt các cảnh báo nhưng điều đó là tốt.


functioncần thiết?
AL

0

Javascript ES6, 108 107 ký tự

107 ký tự, chuỗi kết quả được cắt

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

Kiểm tra:

["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"
]


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.