Правило большого пальца для заглавной буквы


30

Согласно этому сайту, общее правило, рекомендованное Руководством по стилю типографии правительства США, гласит :

Используйте заглавные буквы в названиях публикаций и документов, кроме a, an, the, by, by, for, in, on, up, and, as, но, or, and not.

Возможно, это не так, поскольку я не могу найти такую ​​рекомендацию в Руководстве по стилю , но давайте все равно воспользуемся этим правилом.


Соревнование

Если задана строка ввода, состоящая из строчных слов, разделенных пробелами, выведите заглавную строку в соответствии со следующими правилами

  • Первое и последнее слово пишется с большой буквы.
  • Все остальные слова прописными буквами, за исключением , , , на , по , на , в , из , на , к , до , и , в качестве , но , или , и ни .

Входная строка будет содержать хотя бы одно слово, а каждое слово содержит хотя бы одну букву и только символы от aдо z.

Это сложная задача для гольфа, поэтому старайтесь использовать как можно меньше байтов на выбранном вами языке. Вы можете написать полную программу или функцию для выполнения задачи.

Testcases

"the rule of thumb for title capitalization" -> "The Rule of Thumb for Title Capitalization"
"programming puzzles and code golf" -> "Programming Puzzles and Code Golf"
"the many uses of the letter a" -> "The Many Uses of the Letter A"
"title" -> "Title"
"and and and" -> "And and And"
"a an and as at but by for in nor of on or the to up" -> "A an and as at but by for in nor of on or the to Up"
"on computable numbers with an application to the entscheidungsproblem" -> "On Computable Numbers With an Application to the Entscheidungsproblem"

1
Должны ли начальные / конечные слова быть прописными, даже если они находятся в списке исключений? В ваших примерах сказано «да», но в спецификации написано только слова, написанные с заглавной буквы, если они отсутствуют в списке, и ничего о первом / последнем слове. Обратите внимание, что эти две возможности явно различаются: одна представляет собой простой фильтр, а вторая требует особого поведения в (буквальных) краевых случаях.
CAD97

3
@ CAD97 Правила для заглавных букв - это два пункта, а не Цитата. И первый пункт маркировки гласит: «Первое и последнее слово пишется с большой буквы». а второй говорит: «Все другие слова пишутся с большой буквы, кроме ...», что означает, что первое и последнее слова всегда пишутся с большой буквы.
Лайкони

Я как-то пропустил это. Тем не менее, спасибо за разъяснения.
CAD97

Я не уверен, что действительно необходимо указать, что каждое слово содержит хотя бы одну букву. :)
Дэвид Конрад

Ответы:


11

Python 2, 118 байт

Смотри, мама, нет регулярных выражений!

for w in`input()`.split():print[w.title(),w][`w`in"'a'an'and'as'at'the'by'but'for'nor'in'of'on'or'to'up'"].strip("'"),

Входные данные должны быть заключены в кавычки. У выхода есть завершающий пробел и нет завершающего перевода строки (я полагаю, что все в порядке). Проверьте все контрольные примеры на Ideone .

объяснение

Давайте возьмем входные данные в a or anкачестве нашего примера.

Использование Python 2 в `x`ярлык repr, мы оборачиваем ввод в одиночных кавычках: 'a or an'. Затем мы разделяем пробел и перебираем слова.

Внутри петли мы берем repr снова . Для первых и последних слов это дает "'a"и "an'". Другими словами, это дает 'or'. Мы хотим избежать использования заглавных букв, если они соответствуют последнему шаблону и находятся в списке коротких слов. Таким образом, мы можем представить список слов в виде строки "'a'an'...'up'"и знать, что reprлюбое короткое слово будет подстрокой.

`w` in "..."дает логическое значение, которое мы можем рассматривать как 0или 1для целей индексации в списке [w.title(), w]. Короче говоря, мы ставим регистр в название слова, если оно находится в начале, в конце или нет в списке коротких слов. Иначе мы оставим это в покое. К счастью, title()все еще работает как ожидалось с вводом, как 'a.

Наконец, мы убираем любые одиночные кавычки из слова и печатаем его через пробел.


8

05AB1E , 68 61 байт

Сохранено 7 байтов благодаря Аднану

™ð¡Dg<UvyN__NXQ_“a€¤€€€›€‹€‡€†€‚€‰€„€¾€ƒ€œ€³€—š¯“#™yå&&il})ðý

Попробуйте онлайн!

объяснение

“a€¤€€€›€‹€‡€†€‚€‰€„€¾€ƒ€œ€³€—š¯“словарная строка в переводе a an the at by for in of on to up and as but or nor.

™                          # title case input string
ð¡                         # split on spaces
Dg<U                       # store index of last word in X

vy                         # for each word
  N__                      # is it not first index?
     NXQ_                  # is it not last index
         “...“             # the compressed string 
              #            # split on spaces
               ™           # convert to title case
                yå         # is current word in this list?
                  &&       # and the 3 previous conditions together
                    il     # if all are true, convert to lower case
                      }    # end loop
)ðý                        # wrap stack in list and join by spaces

2
Меня не перестает удивлять то, что вам удается достичь с помощью короткой цепочки совершенно неузнаваемых персонажей. Похоже, это работает тогда :) +1
ElPedro

Ба! Я так близко, и я не могу найти способ сбрить персонажа.
mbomb007

@ mbomb007: Лучше поторопитесь, прежде чем Jelly, MATL или какой-либо другой язык, который может применять функции к индексам, придет и победит это :) Я, кажется, тоже помню язык со сжатым регулярным выражением, но не могу вспомнить, как он назывался. Это достаточно долго, чтобы можно было играть в гольф.
Эминья


@Adnan: я начал так, но только с 3-х символьных слов (которые закончились дольше), но я также не рассматривал возможность взять 2-х символьные слова ... aвместо того, чтобы также €…сохранять дополнительный байт, если с этим :) Спасибо!
Эминья

7

GNU sed 81 74 73 байта

Включает +1 для -r

s/\b./\u&/g
:;s/.(And?|A[st]?|The|By|But|[FN]or|In|O[fnr]|To|Up) /\L&/;t

Первая строка заглавной буквы каждого слова. Вторая переключает все необходимые слова обратно в нижний регистр.

Попробуйте онлайн!


6

Сетчатка, 69 66 байт

Используйте заглавные буквы первой буквы каждого слова, затем измените выбранные слова на строчные, если они не являются первым или последним словом. Там есть пробел в конце последней строки.

T`l`L`\b.
+T`L`l` (And?|A[st]?|The|By|But|[FN]or|In|O[fnr]|To|Up) 

Попробуйте онлайн

Это также работает .вместо первого пробела.

Есть много регулярных выражений с одинаковой длиной, но я не могу найти способ обрезать их больше ...


(Этот подход также составляет 69 байт в Pip, но я не могу использовать +хитрость, чтобы сократить его.)
DLosc

@DLosc Спасибо. Идк, почему я этого не видел. Я был близко.
mbomb007

3

JavaScript (ES6), 141 138 135 133 байта

Сохранено 3 байта благодаря mbomb007

s=>s.replace(/(\w+)( ?)/g,(a,w,n,i)=>i&&n&&/^(a[nst]?|the|by|in|of|on|to|up|and|but|[fn]?or)$/.exec(w)?a:a[0].toUpperCase()+a.slice(1))

Контрольные примеры


3

Желе , 58 байт

“Ð/ṃƇ¬þṄẊƙ€,⁽ṙƬ®OṪJ"ɦ3×kf3Ṙç%ġu’b26ịØaṣ”z
e€¢¬T;2Ḷ¤
ḲŒtǦK

TryItOnline! или запустите все тесты

Как?

Сжатая строка с пробелами, разделяющими слова, будет 47байтами, а разделение 1- на 48байты.

Две неразделенные сжатые строки слов длины 2и 3(с «a» в конце единицы) будут соответственно 40байтами плюс, 2чтобы разделить каждую и 1объединить их для 45байтов.

Одно базовое число 250, как описано ниже, представляет собой 32байты, которые затем 3преобразуются в основание 26 3для индексации в строчный алфавит и 3разделения его на неиспользуемый символ 'z'для 41байтов.

Итак, поиск по словам не для заглавных букв:
“Ð/ṃƇ¬þṄẊƙ€,⁽ṙƬ®OṪJ"ɦ3×kf3Ṙç%ġu’
был сформирован так:

Возьмите эти слова и соедините их с разделителем:
s="a an the at by for in of on to up and as but or nor"

Следующая метка 'a'как 1, 'b'как 2с разделителем как 0:

alpha = ' abcdefghijklmnopqrstuvwxyz'
x = [alpha.index(v) for v in s]
x
[1,0,1,14,0,20,8,5,0,1,20,0,2,25,0,6,15,18,0,9,14,0,15,6,0,15,14,0,20,15,0,21,16,0,1,14,4,0,1,19,0,2,21,20,0,15,18,0,14,15,18]

Преобразуйте это в базовое 26число (последняя использованная буква 'y'плюс цифра для разделителя, код Python для этого:
n=sum(v*26**i for i,v in enumerate(x[::-1]))

Преобразуйте это в базовый 250номер (используя список для цифр):

b=[]
while n:
    n,d = divmod(n,250)
    b=[d]+b
b
[16,48,220,145,8,32,202,209,162,13,45,142,244,153,9,80,207,75,35,161,52,18,108,103,52,205,24,38,237,118]

Поиск символов в этих индексах в кодовой странице желе:

codepage = '''¡¢£¤¥¦©¬®µ½¿€ÆÇÐÑ×ØŒÞßæçðıȷñ÷øœþ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~¶°¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾ƁƇƊƑƓƘⱮƝƤƬƲȤɓƈɗƒɠɦƙɱɲƥʠɼʂƭʋȥẠḄḌẸḤỊḲḶṂṆỌṚṢṬỤṾẈỴẒȦḂĊḊĖḞĠḢİĿṀṄȮṖṘṠṪẆẊẎŻạḅḍẹḥịḳḷṃṇọṛṣṭụṿẉỵẓȧḃċḋėḟġḣŀṁṅȯṗṙṡṫẇẋẏż«»‘’“”'''
r=''.join(codepage[i-1] for i in b)
r
'Ð/ṃƇ¬þṄẊƙ€,⁽ṙƬ®OṪJ"ɦ3×kf3Ṙç%ġu'

(примечание: поскольку фактическая реализация является биективной, если бы она bимела какие-либо 0цифры, сначала нужно было бы ее перенести)

Остальные:

ḲŒtǦK - Main link: title string
Ḳ      - split on spaces
    ¦  - apply to indexes
   Ç   -     given by calling the last link (1) as a monad (with the split title string)
 Œt    -     title case (first letter of each (only) word to upper case)
     K - join on spaces

e€¢¬T;2Ḷ¤ - Link 1, find indexes to capitalise: split title string
e€        - is an element of, for €ach
  ¢       - the result of calling the last link (2) as a nilad
   ¬      - logical not
    T     - get the truthy indexes (indexes of words that are not in the list)
     ;    - concatenate with
        ¤ - nilad followed by link(s) as a nilad
      2Ḷ  - range(2) -> [0,1]
                (we always want to capitalise the first index, 1, and the last index, 0)

“Ð/ṃƇ¬þṄẊƙ€,⁽ṙƬ®OṪJ"ɦ3×kf3Ṙç%ġu’b26ịØaṣ”z - Link 2, make the word list: no arguments
“Ð/ṃƇ¬þṄẊƙ€,⁽ṙƬ®OṪJ"ɦ3×kf3Ṙç%ġu’          - the base 250 number
                                b26       - convert to base 26
                                   ị      - index into
                                    Øa    - lowercase alphabet
                                      ṣ   - split on
                                       ”z - literal 'z' (the separator 0 indexes into `z`)

2

PHP, 158 байт

10 байтов сохранено @Titus

foreach($w=explode(" ",$argv[1])as$k=>$v)echo" "[!$k],$k&&$k+1<count($w)&&preg_match("#^(a[snt]?|and|[fn]or|up|by|but|the|to|in|o[rnf])$#",$v)?$v:ucfirst($v);

Предыдущая версия PHP, 174 байта

foreach($w=explode(" ",$argv[1])as$k=>$v)$k&&$k+1<count($w)&&in_array($v,[a,an,the,at,by,"for",in,of,on,to,up,"and","as",but,"or",nor])?:$w[$k]=ucfirst($v);echo join(" ",$w);

Эхо в цикле экономит 10 байтов:foreach(...)echo" "[!$k],(condition)?$v:ucfirst($v);
Тит

2

TI-Basic, 295 + 59 + 148 = 502 байта

Теперь вы можете заработать на своем калькуляторе. Отлично подходит для школы :)

Основная программа, 295 байт

По сути, хитрость в подборе слов, чтобы Aне стало ничего, заключалась в aтом, чтобы заключить в них пробелы, например, заменить " A "на " a ". Это также автоматически делает так, чтобы первое и последнее слова оставались заглавными, потому что они не имеют пробела с обеих сторон и, таким образом, не соответствуют ни одному из слов. (Гений, правда? И супер длинный, потому что строчные буквы составляют два байта каждая ...)

"("+Ans+")→Str1
"@A ~ a@An ~ an@The ~ the@At ~ at@By ~ by@For ~ for@In ~ in@Of ~ of@On ~ on@To ~ to@Up ~ up@And ~ and@As ~ as@But ~ but@Or ~ or@Nor ~ nor@→Str2
For(I,2,length(Ans
If "@"=sub(Str2,I-1,1
Then
" "+Str1+"~"+sub(Str2,I,inString(Str2,"@",I)-I)+" "
prgmQ
Ans→Str1
End
End

Подпрограмма ( prgmQ), 59 байт:

Ans→Str9
inString(Ans,"~
sub(Str9,Ans,length(Str9)-Ans+1→Str8
Str9
prgmR
Repeat Str9=Ans+Str8
Ans+Str8→Str9
prgmR
End

Подпрограмма ( prgmR), 148 байт:

Ans→Str0
inString(Ans,"~→Z
inString(Str0,"~",Ans+1→Y
inString(sub(Str0,1,Z-1),sub(Str0,Z+1,Ans-Z-1→X
sub(Str0,1,-1+inString(Str0,"~
If X
sub(Str0,1,X-1)+sub(Str0,Y+1,length(Str0)-Y)+sub(Str0,X+length(sub(Str0,Z+1,Y-Z-1)),Z-X-length(sub(Str0,Z+1,Y-Z-1

PS ~представляет токен 0x81и @представляет токен 0x7F, узнайте больше здесь .


2

Java 7, 271 259 258 байт

String c(String x){String a[]=x.split(" "),s=" ",r=w(a[0])+s;for(int i=0,l=a.length-1;i<l;r+=(!s.matches("^(a[nst]?|the|by|in|of|on|to|up|and|but|[fn]?or)$")|i==l?w(s):s)+" ")s=a[++i];return r;}String w(String w){return(char)(w.charAt(0)-32)+w.substring(1);}

Ungolfed & тестовый код:

Попробуй это здесь.

class M{
  static String c(String x){
    String a[] = x.split(" "),
           s = " ",
           r = w(a[0]) + s;
    for(int i = 0, l = a.length-1; i < l; r += (!s.matches("^(a[nst]?|the|by|in|of|on|to|up|and|but|[fn]?or)$") | i == l
                                                 ? w(s)
                                                 : s)   + " "){
      s = a[++i];
    }
    return r;
  }

  static String w(String w) {
    return (char)(w.charAt(0) - 32) + w.substring(1);
  }

  public static void main(String[] a){
    System.out.println(c("the rule of thumb for title capitalization"));
    System.out.println(c("programming puzzles and code golf"));
    System.out.println(c("the many uses of the letter a"));
    System.out.println(c("title"));
    System.out.println(c("and and and"));
    System.out.println(c("a an and as at but by for in nor of on or the to up"));
    System.out.println(c("on computable numbers with an application to the entscheidungsproblem"));
  }
}

Выход:

The Rule of Thumb for Title Capitalization 
Programming Puzzles and Code Golf 
The Many Uses of the Letter A 
Title 
And and And 
A an and as at but by for in nor of on or the to Up 
On Computable Numbers With an Application to the Entscheidungsproblem 

1

Groovy, 131 129

Два байта сохранены благодаря carusocomputing

{it.split()*.with{a->a in "a an the at by for in of on to up and as but or nor".split()?a:a.capitalize()}.join(" ").capitalize()}

Хорошо, я был в 137; ты победил. Удалите его i->и используйте, itчтобы сохранить 2 байта. {it.split()*.with{a->a in "a an the at by for in of on to up and as but or nor".split()?a:a.capitalize()}.join(" ").capitalize()}
Волшебная Осьминога Урна

1
Я не знаю Groovy, но действительно ли это заглавная буква первого и последнего слова?
Эминья

@Emigna заключительные заглавные буквы, начинающиеся с одного из слов.
Волшебная урна осьминога

@ Emigna не совсем, я пропустил это требование (последнее слово должно быть написано заглавными буквами). Мне нужно настроить мой ответ.
Кшиштоф Атласик

Два использования .capitalize()занимают много байтов. Есть ли короткий способ, которым вы можете сделать псевдоним .capitalize()?
Cyoce

1

C #, 305 байт

Еще много возможностей для улучшения, но здесь вы идете:

s=>{;var b=s.Split(' ');b[0]=((char)(b[0][0]-32))+b[0].Substring(1);int i=0,n=b.Length;for(;++i<n;)if(!"a,an,the,at,by,for,in,of,on,to,up,and,as,but,or,nor".Split(',').Contains(b[i]))b[i]=((char)(b[i][0]-32))+b[i].Substring(1);b[n-1]=((char)(b[n-1][0]-32))+b[n-1].Substring(1);return string.Join(" ",b);};

1

Рубин, 123 117 111 102 байта

->s{s.gsub(/ .|^./,&:upcase).gsub(/ (A[nts]?|The|By|In|To|Up|And|But|[NF]or|O[rnf])(?= )/,&:downcase)}

Извините за все правки - это должно быть последним.


1

Python, 177 байт

Поставляется в функциональном формате для сохранения байтов. Это не особенно конкурентный ответ, но тот, который не требует repr()или regexобманывает. Это также не зависит от версии; это работает с Python 2 или 3.

Хотя, возможно, это очень нестандартное решение.

def t(s):
 w="a an the the at by for in of on to up and as but or nor".split()
 l=[(s.title(),s)[s in w]for s in s.split()]
 for x in(0,-1):l[x]=l[x].title()
 return' '.join(l)

1

PHP, 109 142 байта

<?=preg_replace_callback("# (A[snt]?|And|[FN]or|Up|By|But|The|To|In|O[rnf])(?= )#",function($m){return strtolower($m[0]);},ucwords($argv[1]));

Слияние ответов пользователя 59178 и mbomb007 .

Прописные буквы первой буквы каждого слова, затем строчные буквы всех слов из списка, окруженные пробелами.
К сожалению, обратный вызов должен работать на полную комплектацию; это стоит 29 байт.


это работает не дляa an and as at but by for in nor of on or the to up
Йорг Хюльсерманн

1

Ракетка 353 байта

(define(cap i)(set! i(string-append i))(define c(string-ref i 0))(string-set! i 0(if(char-upper-case? c)c(integer->char(-(char->integer c)32))))i)
(let*((ex(list"a""an""the""at""by""for""in""of""on""to""up""and""as""but""or""and""nor"))(sl(string-split s)))
(string-join(for/list((i sl)(n(in-naturals)))(cond[(= n 0)(cap i)][(member i ex)i][(cap i)]))))

Ungolfed:

(define (f s)

  (define (cap i)                 ; sub-fn to capitalize first letter of a word
    (set! i (string-append i))
    (define c (string-ref i 0))
    (string-set! i 0
                 (if (char-upper-case? c)
                     c
                     (integer->char (-(char->integer c)32))))
    i)

  (let* ((ex (list "a""an""the""at""by""for""in""of""on""to""up""and""as""but""or""and""nor"))
         (sl (string-split s)))
    (string-join
     (for/list
         ((i sl)
          (n (in-naturals)))
       (cond
         [(= n 0) (cap i)]
         [(member i ex) i]
         [(cap i)]
         )))))

Тестирование:

(f "the rule of thumb for title capitalization")

Выход:

"The Rule of Thumb for Title Capitalization"

1

Java 7, 431 317 311 байт

Спасибо @KevinCruijssen за 114 байтов.
Спасибо @RosLup за сохранение 6 байтов.

String c(String s){String v="",x,l[]=s.split(" "),b[]={"a","an","the","at","but,"by","for","in","of","on","to","‌​up","as","or","and","nor"};int i=0,f=0,z=0;for(String c:l){for(f=0;f<b.length;z=c.equals(b[f++])|z>0?1:0);x=(char)(c.charAt(0)-32)+c.substring(1);v+=(z>0?i<1|i>l.length-2?x:c:x)+" ";i++;}return v;}

ungolfed

первый ответ выше 250 байт

 static String c(String s) {
      String v = "", x, l[] = s.split(" "),
b[]={"a","an","the","at","by","for","in","of","on","to",
                                         "‌​up","and","as","or","nor","but"};
    int i , f , z = i = f = 0;
    for (String c : l) {

   for (f = 0; f < b.length; z = c.equals( b[f++] ) | z > 0 ? 1 : 0);
        x = (char)(c.charAt(0) - 32) + c.substring(1);

        v += (z > 0 ? i < 1 | i > l.length - 2 ? x : c : x) + " ";
        i++;
   }
    return v;
    }

1
Это было слишком много, чтобы резюмировать в комментарии, но вы можете добавить это к следующему: String f(String s){String v="",x,l[]=s.split(" "),b[]={"a","an","the","at","by","for","in","of","on","to","up","and","as","but","or","and","nor"};int i=0,f=0,z=0;for(String c:l){for(f=0;f<b.length;z=c.equals(b[f++])|z>0?1:0);x=(char)(c.charAt(0)-32)+c.substring(1);v+=z>0?i<1|i++==l.length-1?x:c:x)+" ";}return v;}( 314 байт ) Я предлагаю взглянуть на то, что я изменил в качестве подсказок в следующий раз. :) PS: я выложил ответ с другим подходом ( 259 байт ).
Кевин Круйссен

1
Особенно те вещи, c.substring(0,1).toUpperCase()+c.substring(1,c.length())+" "которые вы делали дважды, должны заставить вас задуматься о том, чтобы как-то использовать его снова. И объединенные инициализации, как вы сделали правильно с int, но по какой-то причине не с String. Кроме того, нет необходимости в дополнительном, booleanкогда вы можете сохранить как int0 или 1, а затем проверить его >0. И я бы старался избегать скобок и breakкак можно больше; обычно есть хитрость, чтобы избавиться от них, как for(f=0;f<b.length;z=c.equals(b[f++])|z>0?1:0);я показал. :)
Кевин Круйссен

1
Так много учиться и спасибо за помощь всегда (да здравствует Nederland;)
Numberknot

1
О, я сделал ошибку копирования-вставки .. Должно быть так String c(String s){String v="",x,l[]=s.split(" "),b[]={"a","an","the","at","by","for","in","of","on","to","up","and","as","but","or","and","nor"};int i=0,f=0,z=0;for(String c:l){for(f=0;f<b.length;z=c.equals(b[f++])|z>0?1:0);x=(char)(c.charAt(0)-32)+c.substring(1);v+=(z>0?i<1|i++>l.length-2?x:c:x)+" ";}return v;}И не проблема. :) Я также многому научился, когда был новичком в код-гольфе. Я просто делаю список с каждым общим советом по Codegolf, который я изучаю, и иногда смотрю / обновляю его. Но мой код все еще часто используется другими игроками.
Кевин Круйссен

1
В строке b [] есть 2 'и' это нормально?
РосЛюП

1

PHP 117 118 112 байт

<?=strtr(ucwords(preg_replace("# (?=(a[snt]?|and|[fn]or|up|by|but|the|to|in|o[rnf]) )#","!",$argv[1])),'!',' ');

Использует поведение ucwords()и экранирует соответствующие слова, которые заключены в пробелы, а затем удаляет escape-символы.

Я скопировал (a[snt]?|and|[fn]or|up|by|but|the|to|in|o[rnf])ответ из Jörg Hülsermann, но, поскольку подход совершенно другой, я публикую его как отдельный ответ.

редактирование: ошибка, замеченная Титом, исправляющая его стоимость 1 байт. также: 6 байтов сохранено благодаря его полезному комментарию о strtr


Сохранить 6 байтов с strtrвместо str_replace. Или добавьте слова с помощью <>drop the str_replaceand drop и используйте вывод HTML.
Тит

В некоторых случаях вы можете использовать preg_filterвместо preg_replace. Я не пробовал это с вашим решением
Йорг Хюльсерманн

Регулярное выражение не будет работать для двух слов из списка подряд; тест nice try for a start. Замена одного из пробелов утверждением решает это (+4 байта).
Тит

К сожалению preg_filter, потерпел неудачу в titleтесте, ничего не возвращая
user59178

1

Чистый bash - 253

(внешние программы не называются) - необходим bash v4

declare -A b;for x in A An The At By For In Of On To Up And As But Or Nor;do b[$x]=1;done
while read -a w;do
n=${#w[@]};o[0]=${w[0]^}
for((i=1;i<n-1;i++)){
g=${w[$i]^};((${b[$g]}))&&o+=(${g,,})||o+=($g);}
((n>1))&&o[$n]=${w[-1]^}
echo ${o[@]};o=()
done

нормальный вид с комментариями

#create the "blacklist"
declare -A b
for w in A An The At By For In Of On To Up And As But Or Nor
do
    b[$x]=1
done

# logic:
# read each line (split by words) into array
# and each word is assigned capitalized to the new output array
# but the blacklisted ones

#read each line to array w (split on spaces)
while read -a w
do
    n=${#w[@]}         # get the number of words
    o[0]=${w[0]^}          # copy the capitalized word1
    for((i=1 ; i<n-1 ; i++)) { # loop over 2 up to last -1 words

        g=${w[$i]^}    # for the given word
        # check if it is in the blacklisted ones
        # if yes - convert to lowercase, if not leave as it is
        # and append to the output array
        (( ${b[$g]} )) && o+=(${g,,}) || o+=($g)
    }
    # capitalize the last word if here is more words
    (( n>1 )) && o[$n]=${w[-1]^}
    # make a line from the words
    echo ${o[@]}
    o=() #cleanup
done

выход

Title
And and And
The Rule of Thumb for Title Capitalization
Programming Puzzles and Code Golf
The Many Uses of the Letter A
A an and as at but by for in nor of on or the to Up
On Computable Numbers With an Application to the Entscheidungsproblem

1

Japt , 71 байт

£`a  e  by f     up d  ¿t  n`¸aX >0©Y¦0©YĦZl ?X:Xg u +XÅ}S

Попробуйте онлайн!

Объяснение:

£`a  e  by f     up d  ¿t  n`¸aX >0©Y¦0©YĦZl ?X:Xg u +XÅ}S
£`...`qS aX >0&&Y!=0&&Y!=UqS l -1?X:Xg u +Xs1}S

£                                            }S   // Split at spaces and map each item X by this function:
 `...`                                            //  Backticks are used to decompress strings
      qS                                          //  Split the decompressed string at spaces.
         aX >J                                    //  If this contains X
              &&Y!=0                              //  and the index is non-zero (it's not the first word)
                    &&Y!=UqS l -1                 //  and the index is not the length of the input -1 (it's not the last word),
                                 ?X               //  return X.
                                   :Xg u +Xs1     //  Else, return X capitalized. (Literally X[0].toUpperCase() + X.slice(1))
                                             }S   // Rejoin with spaces

Одна из моих любимых функций Japt - сжатие строк, использующее библиотеку shoco .

Вы можете сжать строку, обернув ее в Oc"{string}"Oc"a an the at by for in of on to up and as but or nor"

Затем распакуйте его с помощью кавычек или Od"{compressed string}"Od"a e by f up d ¿t n"


-SФлаг был добавлен после того, как эта проблема была опубликована, поэтому ваше текущее решение не является конкурирующим. Тем не менее, я думаю, что вы можете сделать £...+XÅ}S, что будет конкурировать за тот же счетчик байтов ( попробуйте онлайн! )
ETHproductions

Как, по вашему мнению, сравнивает shoco со сжатием словаря в Jelly?
Роберт Фрейзер,

@RobertFraser По сравнению с желе, это не очень хорошо для сжатия строк английских слов, но это очень хорошо для сжатия строк произвольных строчных букв, что очень удобно иногда.
ETHproductions

1

Чистый bash - 205 192 181 байт

tc(){
while read -a x
do x=(${x[@]^})
for ((i=1;i<${#x[@]}-1;i++))
do
case "${x[i]}" in
A|A[nts]|The|By|[FN]or|In|O[fnr]|To|Up|And|But)x[i]=${x[i],};;
esac
done
echo ${x[@]}
done
}

Как и ответ jm66 tc принимает стандартный ввод.


0

На самом деле , 79 байтов

' ,ÿsd@p@`;0"A0An0The0At0By0For0In0Of0On0To0Up0And0As0But0Or0Nor"síu'ù*ƒ`Moq' j

Попробуйте онлайн!

Объяснение:

' ,ÿsd@p@`;0"longstring"síu'ù*ƒ`Moq' j
' ,ÿs                                   title case input, split on spaces
     d@p@                               pop first and last words to stack
         `;0"longstring"síu'ù*ƒ`M       for every word except the first and last:
          ;0"longstring"s                 duplicate word, split the long string on 0s
                         íu               1-based index of word in list (0 if not found)
                           'ù*            "ù"*(index)
                              ƒ           execute the resulting string as a function (lowercases word if it's in the list)
                                 oq' j  put the first and last word back in the list, join with spaces

0

Пакетная, 323 байта

@echo off
set s=
for %%w in (@%*@)do call:w %%w
echo%s%
exit/b
:w
for %%s in (a an the at by for in of on to up and as but or nor)do if %%s==%1 set s=%s% %1&exit/b
set w=%1
set w=%w:@=%
set f=%w:~0,1%
for %%c in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)do call set f=%%f:%%c=%%c%%
set s=%s% %f%%w:~1%

С комментариями:

@echo off
rem Start with an empty output string
set s=
rem Wrap the parameters in @ signs to identify the first and last words 
for %%w in (@%*@) do call :w %%w
rem Ignore the leading space when printing the result
echo%s%
exit/b
:w
rem Check whether this is a word that we don't change
for %%s in (a an the at by for in of on to up and as but or nor) do if %%s==%1 set s=%s% %1&exit/b
set w=%1
rem Delete any @ signs from the first and last words
set w=%w:@=%
rem Get the first character
set f=%w:~0,1%
rem Case insensitively replace each upper case letter with itself
for %%c in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do call set f=%%f:%%c=%%c%%
rem Concatenate with the rest of the word
set s=%s% %f%%w:~1%
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.