La regola empirica per la capitalizzazione del titolo


30

Secondo questo sito regola generale raccomandato dal governo degli Stati Uniti Printing Office Manuale Stile IS

Scrivi in ​​maiuscolo tutte le parole nei titoli di pubblicazioni e documenti, eccetto a, an, the, at, by, for, in, of, on, to, up, and, as, but, o, and nor.

Questo potrebbe non essere vero perché non riesco a trovare una simile raccomandazione nel Manuale di stile , ma usiamo comunque questa regola.


La sfida

Data una stringa di input composta da parole minuscole delimitate da spazi, genera la maiuscola della stringa in base alle seguenti regole

  • La prima e l'ultima parola sono in maiuscolo.
  • Tutte le altre parole sono capitalizzate, eccetto una , una , il , a , da , per , a , a , a , a , alto , e , come , ma , o , e .

La stringa di input conterrà almeno una parola e ogni parola contiene almeno una lettera e solo caratteri da aa z.

Questa è una sfida del codice golf, quindi prova a utilizzare il minor numero di byte possibile nella lingua che preferisci. È possibile scrivere un programma completo o una funzione per eseguire l'attività.

Casi test

"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
Le parole di inizio / fine devono essere scritte in maiuscolo anche se si trovano nell'elenco di esclusione? I tuoi esempi dicono di sì, ma la specifica dice solo le maiuscole a meno che non siano nell'elenco, e nulla sulla prima / ultima parola. Si noti che le due possibilità sono nettamente diverse, una è un semplice filtro e la seconda richiede un comportamento speciale in casi limite (letterali).
CAD97,

3
@ CAD97 Le regole per la capitalizzazione sono i due punti elenco, non il preventivo. E il primo punto indica "La prima e l'ultima parola sono in maiuscolo". e la seconda dice "Tutte le altre parole sono in maiuscolo, tranne ...", il che significa che la prima e l'ultima parola sono sempre in maiuscolo.
Laikoni,

L'ho perso, in qualche modo. Tuttavia, grazie per il chiarimento.
CAD97,

Non sono sicuro che sia davvero necessario specificare che ogni parola contiene almeno una lettera. :)
David Conrad,

Risposte:


11

Python 2, 118 byte

Guarda mamma, niente regex!

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

L'input deve essere racchiuso tra virgolette. L'output ha uno spazio finale e nessuna riga finale (suppongo che vada bene). Verifica tutti i casi di test su Ideone .

Spiegazione

Prendiamo l'input a or ancome nostro esempio.

Utilizzando Python 2 `x`scorciatoia per repr, ci avvolgiamo l'ingresso tra apici: 'a or an'. Quindi ci dividiamo su spazi bianchi e ripetiamo le parole.

All'interno del ciclo, prendiamo di repr nuovo . Per la prima e l'ultima parola, questo dà "'a"e "an'". Per altre parole, dà 'or'. Vogliamo evitare le parole in maiuscolo se si adattano a quest'ultimo schema e sono nell'elenco delle parole brevi. Quindi possiamo rappresentare l'elenco di parole come stringa "'a'an'...'up'"e sapere che la reprparola breve sarà una sottostringa.

`w` in "..."fornisce un valore booleano, che possiamo trattare come 0o 1ai fini dell'indicizzazione nell'elenco [w.title(), w]. In breve, cerchiamo la parola titolo se è all'inizio, alla fine o no nell'elenco di parole brevi. Altrimenti, lo lasciamo solo. Fortunatamente, title()funziona ancora come previsto con input simili 'a.

Infine, eliminiamo ogni singola virgoletta dalla parola e la stampiamo con uno spazio finale.


8

05AB1E , 68 61 byte

Salvataggio di 7 byte grazie ad Adnan

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

Provalo online!

Spiegazione

“a€¤€€€›€‹€‡€†€‚€‰€„€¾€ƒ€œ€³€—š¯“è una stringa del dizionario tradotta come 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
Non smette mai di stupirmi di ciò che riesci a ottenere con una breve serie di personaggi totalmente irriconoscibili. Sembra che funzioni allora :) +1
ElPedro,

Bah! Sono così vicino e non riesco a trovare un modo per radere un personaggio.
mbomb007,

@ mbomb007: Meglio sbrigarsi prima che Jelly, MATL o qualche altra lingua che possa applicare funzioni agli indici arrivi e batta questo :) Mi sembra di ricordare anche una lingua con regex compresso, ma non ricordo come si chiamava. Questo è abbastanza lungo da poter essere anche giocabile a golf.
Emigna,

1
Per 62 byte :)
Adnan,

@Adnan: ho iniziato in questo modo, ma solo con le parole a 3 caratteri (che sono finite più a lungo), ma non ho considerato di prendere anche le parole a 2 caratteri ... ainvece di €…salvare un byte aggiuntivo se anche piombo con esso :) Grazie!
Emigna,

7

GNU sed 81 74 73 byte

Include +1 per -r

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

La prima riga mette in maiuscolo la prima lettera di ogni parola. Il secondo riporta tutte le parole richieste in minuscolo.

Provalo online!


6

Retina, 69 66 byte

Scrivi in ​​maiuscolo la prima lettera di ogni parola, quindi modifica le parole selezionate in minuscolo se non sono la prima o l'ultima parola. C'è uno spazio alla fine dell'ultima riga.

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

Provalo online

Questo funziona anche con un .invece del primo spazio.

Ci sono molte regex con la stessa lunghezza, ma non riesco più a trovare un modo per tagliarlo ...


(Questo approccio ha anche 69 byte in Pip, ma non posso usare il +trucco per accorciarlo.)
DLosc,

@DLosc Grazie. Idk perché non l'ho visto. Ero vicino
mbomb007,

3

JavaScript (ES6), 141 138 135 133 byte

Salvato 3 byte grazie a 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))

Casi test


3

Gelatina , 58 byte

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

TryItOnline! oppure esegui tutti i test

Come?

Una stringa compressa con spazi che separano le parole sarebbe 47byte, dividendola costa 1byte, per 48byte.

Due stringhe compresse non separate delle parole di lunghezza 2e 3(con una 'a' alla fine di uno) sarebbero rispettivamente 40byte più 2per dividere ciascuno e 1unirli, per 45byte.

Un numero di base 250 come descritto di seguito è 32byte, quindi 3per convertire in base 26, 3per indicizzare in alfabeto minuscolo e 3per dividerlo sul carattere non utilizzato 'z', per 41byte.

Quindi, la ricerca delle parole per non capitalizzare: si
“Ð/ṃƇ¬þṄẊƙ€,⁽ṙƬ®OṪJ"ɦ3×kf3Ṙç%ġu’
è formata così:

Prendi quelle parole e unisciti a loro con un separatore:
s="a an the at by for in of on to up and as but or nor"

Etichetta successiva 'a'come 1, 'b'come 2con il separatore come 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]

Converti questo in un 26numero di base (l'ultima lettera utilizzata è 'y'più una cifra per il separatore, il codice Python per questo è:
n=sum(v*26**i for i,v in enumerate(x[::-1]))

Converti quello in un 250numero base (usando un elenco per le cifre):

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]

Cerca i personaggi in quegli indici nella tabella codici di jelly:

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

(nota: poiché l'implementazione effettiva è biiettiva, se bavesse qualche 0cifra bisognerebbe effettuare prima il trasferimento)

Il riposo:

ḲŒ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 byte

10 byte salvati da @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);

Versione precedente PHP, 174 byte

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

L'eco nel loop consente di risparmiare 10 byte:foreach(...)echo" "[!$k],(condition)?$v:ucfirst($v);
Tito

2

TI-Basic, 295 + 59 + 148 = 502 byte

Ora puoi capitalizzare sulla tua calcolatrice. Ottimo per la scuola :)

Programma principale, 295 byte

Fondamentalmente, il trucco per abbinare le parole in modo Ache non tutto diventi aè racchiuderlo con spazi, come sostituire " A "con " a ". Questo fa automaticamente in modo che la prima e l'ultima parola rimangano maiuscole, perché non hanno uno spazio su entrambi i lati e quindi non corrispondono a nessuna delle parole. (Genio, vero? E molto lungo perché le lettere minuscole sono due byte ciascuna ...)

"("+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

Sottoprogramma ( prgmQ), 59 byte:

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

Sottoprogramma ( prgmR), 148 byte:

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 ~rappresenta il token 0x81e @rappresenta il token 0x7F, ulteriori informazioni qui .


2

Java 7, 271 259 258 byte

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

Codice non testato e test:

Provalo qui.

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

Produzione:

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

Due byte risparmiati grazie al 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()}

Bello, avevo 137 anni; hai vinto. Rimuovilo i->e usalo itper salvare 2 byte. {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()}
Magic Octopus Urn,

1
Non conosco Groovy, ma questo fa in maiuscolo la prima e l'ultima parola?
Emigna,

@Emigna le copertine maiuscole finali iniziano con una delle parole.
Magic Octopus Urn,

@Emigna non proprio, ho perso quel requisito (l'ultima parola deve essere maiuscola). Avrei bisogno di aggiustare la mia risposta.
Krzysztof Atłasik,

I due usi di .capitalize()occupano molti byte. C'è un modo breve in cui puoi creare un alias .capitalize()?
Cyoce,

1

C #, 305 byte

Ci sono ancora molti margini di miglioramento, ma ecco qui:

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

Rubino, 123 117 111 102 byte

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

Ci scusiamo per tutte le modifiche - questa dovrebbe essere l'ultima.


1

Python, 177 byte

Fornito in formato funzione ai fini del salvataggio dei byte. Questa non è una risposta particolarmente competitiva, ma è una che non richiede repr()oregex inganno. È anche indipendente dalla versione; funziona con Python 2 o 3.

Sebbene sia forse una soluzione molto secondo le regole.

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 byte

<?=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]));

Una fusione della risposta di user59178 e mbomb007 .

maiuscolo la prima lettera di ogni parola, quindi minuscole tutte le parole dell'elenco circondate da spazi.
Sfortunatamente, il callback deve operare sul set completo; questo costa 29 byte.


non funziona pera an and as at but by for in nor of on or the to up
Jörg Hülsermann,

1

Racchetta 353 byte

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

test:

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

Produzione:

"The Rule of Thumb for Title Capitalization"

1

Java 7, 431 317 311 byte

Grazie a @KevinCruijssen per 114 byte.
Grazie a @RosLup per aver salvato 6 byte.

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

prima risposta superiore a 250 byte

 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
È stato troppo sintetizzante in un commento, ma è possibile golfare a questo: 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 byte ) Suggerisco di dare un'occhiata a ciò che ho cambiato come suggerimenti per la prossima volta. :) PS: ho pubblicato una risposta con un approccio diverso ( 259 byte ).
Kevin Cruijssen,

1
Soprattutto cose come quelle c.substring(0,1).toUpperCase()+c.substring(1,c.length())+" "che hai fatto due volte dovrebbero farti pensare di riutilizzarlo in qualche modo. E le inizializzazioni combinate come te hanno fatto correttamente con int, ma per qualche ragione non con String. Inoltre, non è necessario alcun extra booleanquando è possibile memorizzare come int0 o 1 e quindi controllarlo >0. E proverei a evitare le parentesi e breakil più possibile; di solito c'è un trucco per sbarazzarsi di loro, come for(f=0;f<b.length;z=c.equals(b[f++])|z>0?1:0);ho mostrato. :)
Kevin Cruijssen,

1
Tante cose da imparare e grazie per essere sempre stato utile (lunga vita a Nederland;)
Numberknot,

1
Oh, ho fatto un errore di copia e incolla. Dovrebbe essere questo 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;}e nessun problema. :) Ho anche imparato molto quando ero nuovo nel golf del codice. Faccio un elenco con tutti i consigli generali su codegolf che imparo e lo guardo / lo aggiorno a volte. Ma il mio codice viene ancora giocato molto da altri.
Kevin Cruijssen,

1
Nella stringa b [] ci sono 2 'e' va bene?
RosLuP,

1

PHP, 117 118 112 byte

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

Utilizza il comportamento ucwords()e sfugge alle parole pertinenti che sono circondate da spazi, quindi elimina i caratteri di escape.

Ho copiato la (a[snt]?|and|[fn]or|up|by|but|the|to|in|o[rnf])risposta di Jörg Hülsermann ma poiché l'approccio è completamente diverso, lo sto pubblicando come risposta separata.

modifica: bug notato da Titus, risolvendolo costa 1 byte. anche: 6 byte salvati grazie al suo utile commento su strtr


Salva 6 byte con strtranziché str_replace. O anteporre le parole con <>e rilasciare the str_replacee utilizzare l'output HTML.
Tito,

In alcuni casi è possibile utilizzare preg_filterinvece di preg_replace. Non l'ho provato con la tua soluzione
Jörg Hülsermann,

Il regex non funzionerà per due parole dall'elenco di seguito; test nice try for a start. Sostituire uno degli spazi con un'asserzione risolve quello (+4 byte).
Tito

Sfortunatamente preg_filterfallirebbe il titletest case, non restituendo nulla.
user59178

1

Puro bash - 253

(nessun programma esterno chiamato) - richiede 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

vista normale con commenti

#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

produzione

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 byte

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

Provalo online!

Spiegazione:

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

Una delle mie funzioni preferite di Japt è la compressione delle stringhe, che utilizza la libreria shoco .

È possibile comprimere una stringa avvolgendola in Oc"{string}"Oc"a an the at by for in of on to up and as but or nor"

Quindi decomprimendolo con i backtick o Od"{compressed string}"Od"a e by f up d ¿t n"


La -Sbandiera è stata aggiunta dopo che questa sfida è stata pubblicata, quindi la tua soluzione attuale non è competitiva. Tuttavia, penso che tu possa fare £...+XÅ}S, che sarebbe in competizione per lo stesso numero di byte ( Provalo online! )
ETHproductions

Come si confronta shoco con la compressione del dizionario di Jelly secondo te?
Robert Fraser,

@RobertFraser Rispetto a Jelly, non è molto bravo a comprimere stringhe di parole inglesi, ma è molto bravo a comprimere stringhe di lettere minuscole arbitrarie, che a volte sono utili.
ETHproductions

1

Puro bash - 205 192 181 byte

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
}

Come la risposta di jm66 tc accetta input standard.


0

In realtà , 79 byte

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

Provalo online!

Spiegazione:

' ,ÿ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

Lotto, 323 byte

@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%

Con commenti:

@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%
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.