Her harfle başlayan ilk kelimeyi bulun


25

Bir dize verildiğinde, her harfle başlayan ilk sözcüğü bulun (büyük / küçük harf duyarlı).

Numune

Ferulas flourish in gorgeous gardens.Giriş olarak kullanmak :

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

Daha sonra, bu örnek için çıktı, tek bir boşlukla birleştirilen eşleşen kelimeler olmalıdır:

"Ferulas in gorgeous"

Meydan okuma

Hem giriş hem de çıkış bir dize gösterimi veya dilinizdeki en yakın alternatif olmalıdır.

Program veya fonksiyona izin verildi.

Sen en az birini olmanın bir kelime düşünebiliriz: lowercase or uppercase letters, digits, underscore.

Bu , bayt cinsinden kazanılan en kısa cevap.

Başka örnekler:

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"

Sondaki / başlangıç ​​alanlarına izin verilir mi? <s> Kelimelerin orijinal dizgede bir boşlukla ayrıldığını varsayabilir miyim? </s>
Qwertiy

Bunu örneklerden anladım, bu yüzden yorumda <s> </s> var. Peki ya kırpma alanları?
Qwertiy

Yanıtlar:


17

Retina , 28 bayt:

M! I` \ b (\ w) (? <! \ \ 1. + B) \ w *
¶
 
  • M! - Her işi eşleştirin ve tüm satırları satırsonları ile ayırarak yazdırın.
  • i - Görmezden gelin.
  • \b(\w) - Her kelimenin ilk harfini yakalayın
  • (?<!\b\1.+)- Harfleri eşleştirdikten sonra, aynı harften başlayan önceki bir kelime olup olmadığını kontrol edin. \1.+en az iki karakter sağlar, bu yüzden şu anki kelimeyi atlıyoruz.
  • \w*- kelimenin kalanını eşleştirin.
    Yukarıdakiler yalnızca kelimelerle eşleşir - diğer tüm karakterler kaldırılır.
  • ¶\n - Yeni satırları boşluklarla değiştirin.

Çevrimiçi deneyin!


9

Retina , 45 bayt

I` \ B ((\ w) \ w *) \ B (<? = \ b \ 2 \ w * \, b. +)

\ W +
 
^ | $

Aynı \wkarakterden başlayarak daha sonraki sözcükleri kaldırmak için basitçe tek bir regex kullanır ( iseçeneğe duyarsız küçük harf ), işlemleri \Wtek bir alana dönüştürür , ardından sonuçtaki öndeki / sondaki alanı kaldırır.

Çevrimiçi deneyin!

Düzenleme: Kullanarak daha kısa bir sürüm için @ Kobi'nin cevabına bakınız.M!`


Kahretsin, zorlukla beni dövdü! Ama aramızdakileri anlayamadım.
GamrCorps

3
Başka bir Retina cevabı ekledim - eğer yeterince farklılarsa bence sorun yok (temel kavram elbette benzer).
Kobi

1
@Kobi Çok daha iyi, bu yüzden onu gördüğüme sevindim :) Retina'nın çizgi seçenekleri hakkında ne kadar çok şey öğrenmem gerektiğini fark etmemi sağlıyor.
Sp3000

Birkaç bayt kurtarmak için bunu yapabilir misin? i` \b((\w)\w*)\b(?<=\b\2\w*\b.+)(birinciden önce bir boşluk \b) Satırlar daha sonra gereksiz mi?
Sızdıran Rahibe,

@KennyLau Ne yazık ki, bunun işe yaradığını sanmıyorum çünkü sözcüklerin boşluklarla ayrılması gerekmez, örneğina...a -> a
Sp3000

9

JavaScript (ES6), 73 71 bayt

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

@ Edc65 sayesinde 2 bayt kaydedildi!

Ölçek

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


Kullanarak parseInt("_",36) = NaN? Küfür!
Sp3000

1
İşin aslı şu ki: işe yarıyor @ Sp3000
edc65

U = regexp kullanmak gerçekten zekice. 2 bayttan s=>s.match(u=/\w+/g).filter(w=>u[w=parseInt(w[0],36)]?0:u[w]=1).join' '
tasarruf edin

@ edc65 Teşekkürler. Tek bir baz-36 rakam için 37 olası çıkış olması aslında oldukça uygun.
user81655

7

Pyth, 23 bayt

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

Çevrimiçi deneyin: Gösteri veya Test Paketi

J:z"\w+"1Girişteki tüm sözcükleri regex kullanarak bulur \w+ve saklar J.

.grhk0Jsözcükleri küçük harfli ilk harflerine göre hMgruplandırır, her gruptan birincisini alır, xDJbu sözcükleri giriş dizesindeki dizine göre sıralar ve jdaralarına boşluk koyar.


4

Perl 6, 39 bayt

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

1
\w+Eşleşmesi gereken kelimeleri düzelten 42 bayt ve substrparçası golf
Jo King

3

C, 142 132 122 bayt

@Tucuxi sayesinde 10 bayt daha hafif!

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

Son çıktı sözcüğünden sonra sonda bir boşluk yazdırır.


1
Eğer için çek tıraş edebilirsiniz c>47ve c<58kullanarak isalnumyerineisalpha
haliç yunusu

3

MATL , 23 bayt

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

Bu, Jakube’in istenmeyen karakterleri kaldırmak ve aynı anda bölmek için bir regexp kullanma fikrini ödünç alıyor .

Giriş, tek tırnak işareti içine alınmış bir dizedir.

Çevrimiçi deneyin!

açıklama

'\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 tuş vuruşlarını

: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

Açıklama:

: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

Bunun ne kadar sürdüğü konusunda gerçekten hayal kırıklığına uğradım. "Geçersiz" karakter (her şey ama a-z, A-Z, _gerçekten üzerimden attı ve boşluk). Eminim bunu yapmanın daha iyi bir yolu vardır:

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

\hBunların hepsiyle eşleştiğinden beri uzayı bekliyorlar, ancak metachar'ı bir aralığa nasıl koyacağımı bulamıyorum. Eğer birinin ipucu varsa, duymayı çok isterim.


3
Neden a-zA-Z_değil \w? basamaklar geçerlidir
edc65

2

Julia, 165 155 151 129 102 bayt

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

Bu bir dizeyi kabul eden ve bir dize döndüren bir işlevdir.

Ungolfed:

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'in yardımıyla 53 byte kurtarıldı!



2

C # (LINQPAD) - 136 128 bayt

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 bayt

Kod:

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

Çevrimiçi deneyin!

Açıklama:

İlk önce 94L32+ç( burada deneyin ) kullanılarak giriş dizisinden silinmesi gereken tüm karakterleri oluştururuz . Bu dizgeyi žj içinde depolanan Jve kaldırmayı kullanarak birleştiririz [a-zA-Z0-9_]( Burada deneyin ). İkinci dizgede bulunan tüm karakterleri, ilk dizgeden kaldırırız ki bu bizi terk edecektir:

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

Bu da burada test edilebilir . Biz Dhiç bu ve mağaza oğalt Xile U-Komut. Daha sonra bu dizgede bulunan tüm karakterleri girişten kaldırdık. Daha sonra ð¡tüm boş dizeleri (kullanarak ""K) kullanarak boşlukları ayırdık . Biz şimdi sahip bu .

Bu, çalışacağımız girdinin temiz versiyonudur. Her elementi kullanarak haritalıyoruz v. Bu ydize değişkeni olarak kullanır . Dizenin ilk karakterini, tüm yasaklanmış karakterlerin bulunduğu bir dizge içeren ¬ve iterek alırız . İlk karakterin (ayrıca kayıt listesine eklenecek olan) genel sürüm sürümünün bu dizgede olup olmadığını kontrol ederiz . Bu bölümün kapsamı: İlk harf yasak karakterler dizisinde bulunmuyorsa ( ), bu mektubu yasak karakterler listesine ekleriz (ile yapılır ) veX!"#$%&'()*+,-./:;<=>?@[\]^`{|}~l©åï>iXX®«Uy yığının üstüne basarız.

Son olarak, dizeler filtrelendiğinde yığına boşluklarla birleştiririz ðý.


1
... açıklama? :-)
Luis Mendo

@LuisMendo Beni hatırlattığın için teşekkürler! Tamamlandı :)
Adnan

2

PHP

Cevapların çoğunda regex kullanımından esinlendiğimde, başlangıçta düzgün bir değişiklik göstermek için regex kullanmadan bunu yapmaya çalıştım, ancak girdi olarak temiz dizelerin bulunmadığı nokta bu fikri mahvetti. Üzgün.

İşlev sargısı ile, 89 bayt

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

İşlev sarıcısı olmadan (önceden bildirilmiş $ s), 73 bayt

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

Açıklama:

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.

Benim tek pişmanlığım harf kutusunu kontrol etmek / dönüştürmek için daha hızlı bir yol bulamadığımdır.


2

Python, 103 bayt

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 Bayt

İstediğimden çok daha uzun sürdü ...

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

Ungolfed

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

Cidden, 43 bayt

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

Çevrimiçi deneyin!

Regex yeteneklerinin eksikliği bunu olması gerekenden çok daha zorlaştırdı.

Açıklama:

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

Yakut 76 Bayt

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

Veya yöntem tanımı ile 88 bayt

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

Ungolfed ve birim testi ile:

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

Regex'te \wsayı karakterleri içerir, böylece [\w\d]değiştirilebilir \w. Ayrıca, nilaradığınızda değerler bir dizideyse join' '(ya da daha iyisi, *' 'daha fazla bayt kaydetmek için kullanabileceğiniz bir kestir), yok olurlar, böylece çağrı compactgereksizdir.
Value Ink,

@KevinLau Teşekkürler. Bu \w\dbenim için utanç verici. Ama eğer kaldırırsam, compactek boşluklar alırım (bkz. ['x',nil,'x']*'y' == 'xyyx'). Yoksa bir şey mi kaçırdım?
Nisanda

Hata! Haklısın. Bu durumda, (list-[p])baytları kaydeder list.compact. Ayrıca, /\w/eşdeğerdir /[\w]/. Son olarak, yerine nilile pve !pile 1(sizin karma sadece içinde truthy değerlerini ihtiyacı beri)
Değer Mürekkep

Teşekkürler, ben, yerine Sözlerinizi ekledi nilile pçalışmaz. Kodumun içinde kullanırsam bir sözdizimi hatası alıyorum. Ben gibi kapsüllemek zorunda (p)- ama sonra yine 3 karakter var.
Nisanda

Ve üçlü çevirin ve o zaman bir byte kaydetmek için çalışır: !f[j=i.upcase]?(f[j]=1;h):p. Ayrıca sadece bunu düşündüm, ama dizge indekslemesi nedeniyle , eserler lehine de kullanmak s.scan(/\w+/)ve kaldırmak . ih[0]
Value Ink,

1

grep ve awk, 68 56 bayt

Senaryo:

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

Açıklama:

  • grep -o Her birini kendi satırına basan yasal kelimeleri eşleştirir.

  • awkher satırın ilk harfini alır, substrküçük harf yapar ve ardından bu tuşla bir karma tablo girişi artırır. Değer, artımdan önce ayarlanmamışsa, satır yazdırılır.

  • echo ... satırları tekrar kelimelere çevirir

Ben daha önce olmayan bir çözüm oluşturmak için çalıştık awkkullanarak uniq, sort, grepve bashama sadece kısa düştü. Düzenlemelerdeki tarih.

Kaçırdığım bazı gelişmeler için Dennis'e teşekkürler.


0

Python 3.5, 138 bayt:

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

Temel olarak, olan şey ..

  1. Basit bir normal ifade kullanarak, program verilen dizedeki küçük veya büyük harf, rakam veya alt çizgi hariç tüm karakterleri boşluklarla değiştirir ve ardından dizgiyi bu boşluklara böler.
  2. Ardından, liste kavrama özelliğini kullanarak, bölünmüş dizedeki tüm sözcükleri yineleyen bir liste oluşturun ve her kelimenin ilk harflerini "t" listesine eklemek için ekleyin.
  3. Süreçte, şu anki kelimenin ilk harfi zaten "t" listesinde değilse, o zaman o kelime ile takip eden boşluk yaratılmakta olan listeye eklenir. Aksi halde, liste "t" yi listelemek için her kelimenin ilk harfini eklemeye devam eder.
  4. Son olarak, bölünmedeki tüm kelimeler yinelendiğinde, yeni listedeki kelimeler bir dizgeye birleştirilir ve döndürülür.

0

PHP 120 bayt

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

Bu bir sürü uyarı oluşturur ama sorun değil.


functiongerekli?
AL

0

Javascript ES6, 108 107 karakter

107 karakter, sonuç dizesi kesildi

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

Ölçek:

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


0

Tcl , 150 bayt

proc F {s D\ {}} {lmap w [split $s] {regsub -all \[^\\w] $w "" f
if {![dict e $D [set k [string tol [string in $f 0]]]]} {dict se D $k $f}}
dict v $D}

Çevrimiçi deneyin!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.