Знайдіть перше слово, починаючи з кожної літери


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>
Qwertiy

Я зрозумів це з прикладів, тому в коментарі є <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
Я додав ще одну відповідь Retina - я думаю, що це нормально, якщо вони досить різні (звичайно, основна концепція схожа).
Кобі

1
@Kobi Це набагато краще, тому я радий це бачити :) Дає мені зрозуміти, скільки ще мені потрібно дізнатися про варіанти лінії Retina, а що ні.
Sp3000

Чи можете ви це зробити, щоб зберегти кілька байт? i` \b((\w)\w*)\b(?<=\b\2\w*\b.+)(пробіл перед першим \b) Чи є рядки після цього непотрібними?
Лина монашка

@KennyLau На жаль, я не думаю, що це працює, оскільки слова не обов'язково розділяються пробілами, наприкладa...a -> a
Sp3000

9

JavaScript (ES6), 73 71 байт

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

Збережено 2 байти завдяки @ edc65!

Тест

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 Дякую Насправді дуже зручно, що існує 37 можливих виходів для однієї базової 36 цифр.
користувач81655

7

Pyth, 23 байти

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

Спробуйте в Інтернеті: Демонстрація або Тестовий набір

J:z"\w+"1знаходить усі слова на вході за допомогою регулярного вираження \w+та зберігає їх у J.

.grhk0Jгрупує слова за їх малою літерою, hMприймає перше з кожної групи, xDJсортує ці слова за їх індексом у вхідному рядку та jdставить пробіли між ними.


4

Perl 6, 39 байт

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

1
42 байти, які фіксують слова, які мають збігатися, \w+і гольфують substrчастину
Jo King

3

C, 142 132 122 байт

На 10 байт легше завдяки @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();}

Друкує пробіл після останнього виводу слова.


1
ви можете голити чеки на c>47та c<58, використовуючи isalnumзамістьisalpha
tucuxi

3

MATL , 23 байти

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

Це запозичує ідею Якубе використовувати повторне позначення для видалення небажаних символів і розділення одночасно.

Введення - це рядок, укладений одинарними лапками.

Спробуйте в Інтернеті!

Пояснення

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

Збережено 53 байти за допомогою Sp3000!



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+ç( Спробуйте тут ). Ми приєднуємося до цього рядка, використовуючи Jта видаляючи, [a-zA-Z0-9_]який зберігається у žj ( Спробуйте тут ). Ми видаляємо всі символи, що знаходяться у другому рядку, з першої рядки, яка залишить нас:

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

Це також можна перевірити тут . Ми Dце ускладнюємо і зберігаємо до Xкоманди U-команда. Потім вилучаємо всі вхідні символи з цього введення. Потім розділяємо на пробіли, використовуючи ð¡та видаляючи всі порожні рядки (використовуючи""K ). Зараз у нас це є .

Це чиста версія вводу, з яким ми будемо працювати. Зображуємо кожен елемент за допомогою v. Для цього використовується yяк змінна рядок. Ми беремо перший символ рядка за допомогою ¬і push X, який містить рядок із усіма забороненими символами ( !"#$%&'()*+,-./:;<=>?@[\]^`{|}~). Ми перевіряємо, чи в цьому рядку використовується lверсія owercase першого символу (яка також буде ©приєднана до реєстру) å. Охоплюється цією частиною:, ï>iякщо перша літера не існує в рядку заборонених символів (X ), ми додаємо цей лист до списку заборонених символів (зроблено з X®«U) і натискаємо yна вершину стека.

Нарешті, коли рядки фільтруються, ми з'єднуємо стек пробілами з ðý.


1
... пояснення? :-)
Луїс Мендо

@LuisMendo Дякую, що нагадали! Готово :)
Аднан

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

У Regex \wвходить число символів, тому [\w\d]його можна замінити на \w. Крім того, якщо nilзначення знаходяться в масиві під час дзвінка join' '(а ще краще *' '- це стенограма, яку можна використовувати для збереження більшої кількості байтів), вони зникають, тому виклик compactне потрібен.
Значення чорнила

@KevinLau Дякую \w\dНезручно для мене. Але якщо я видаляю, compactя отримую додаткові пробіли, (див. ['x',nil,'x']*'y' == 'xyyx'). Або я щось пропустив?
кнут

Упс, ти маєш рацію. У цьому випадку (list-[p])економиться байт list.compact. Також /\w/еквівалентно /[\w]/. Нарешті, можна замінити nilз , pі ваш !pз 1(так як ваш хеш потрібно тільки truthy значення в ньому)
Значення Ink

Спасибі, я додав свої зауваження, Заміщення nilз pне працює. Якщо я використовую його всередині свого коду, я отримую синтаксичну помилку. Мені доводиться інкапсулювати (p)- але тоді у мене знову 3 символи.
кнут

Фліп троичного , а потім він працює , щоб зберегти байти: !f[j=i.upcase]?(f[j]=1;h):p. Також просто думав про це, але через індексацію рядків, використання s.scan(/\w+/)та вилучення на iкористь також h[0]працює.
Значення чорнила

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, grepіbash , але впав трохи менше. Історія в редакціях.

Завдяки Деннісу за деякі вдосконалення я пропустив.


0

Python 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

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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.