Zastosuj angielskie zasady interpunkcyjne

11

Zostałeś zatrudniony do napisania kodu do aplikacji do dyktowania, która pobiera głos ze źródła mówionego, analizuje go jako słowa i zapisuje na ekranie.

Kierownictwo tak naprawdę nie ufa ci tyle mocy w projekcie - niestety nie jesteś w stanie siedzieć i grać w golfa przez cały dzień zamiast wykonywać swoją pracę - więc po prostu dają ci naprawdę proste zadanie do wykonania: obrócić Zdanie z przerywaną interpunkcją w poprawnie sformatowanym zdaniu, gdzie „właściwie sformatowane” zostało zdefiniowane poniżej.

  1. Zdanie to ciąg wejściowy. Słowo to grupa wyróżniających się znaków spacji. Interpunkcja to Słowo, którego pierwszą postacią jest ^.

  2. Słowo jest pisane wielką literą, jeśli pierwsza litera tego słowa nie jest małą literą (słowa pisane wielką literą pasują do wyrażenia regularnego /[^a-z].*/).

  3. Pierwsze słowo zdania musi być pisane wielkimi literami.

  4. A ^COMMAjest przecinkiem ,i ma spację następującą, ale nie poprzedzającą. aaa ^COMMA bbbstaje się aaa, bbb.

  5. A ^COLONto przecinek, który wygląda :.

  6. A ^SEMICOLONto przecinek, który wygląda ;.

  7. A ^PERIODto przecinek, który wygląda .. Słowo po a ^PERIODmusi być pisane wielką literą.

  8. A ^BANGto okres, który wygląda !.

  9. A ^DASHjest znakiem myślnika -i ma spację zarówno poprzedzającą, jak i następującą.

  10. A ^HYPHENjest także znakiem myślnika, -ale nie ma spacji po nim ani przed nią.

  11. Jest ^EMDASHto łącznik (nie myślnik!), Który jest przeliterowany --.

  12. An ^OPENQUOTEjest znakiem cudzysłowu ", którego spacja jest poprzednia, ale nie następująca. Słowo następujące po ^OPENQUOTEmusi być pisane wielkimi literami. Jeśli ^OPENQUOTEpoprzedzone jest słowem, które nie jest interpunkcją, dodaj ^COMMApomiędzy tym słowem a ^OPENQUOTE. Jeśli ^OPENQUOTEpoprzedzona jest interpunkcja, która powoduje, że następne słowo jest pisane wielką literą, powoduje to przejście ^OPENQUOTEdo następnego słowa.

  13. A ^CLOSEQUOTEto digraf, ,"który ma spację następującą, ale nie poprzedzającą. Jeśli ^CLOSEQUOTEjest poprzedzone ^COMMA, ^PERIODlub ^BANG, że interpunkcja znika i ^CLOSEQUOTEjest napisane ,", ."albo !"odpowiednio. Jeśli znikająca interpunkcja określiła wielką literę, ta litera musi nadal występować przy następnym dostępnym słowie.

  14. Początkowe lub końcowe spacje w pełnym wyniku końcowym muszą zostać usunięte, a każdy ciąg dwóch lub więcej spacji z rzędu musi być zwinięty w pojedynczy znak spacji.

  15. Wszelkie przypadki nieuwzględnione powyżej (np. ^COMMA ^COMMALub ^SEMICOLON ^CLOSEQUOTElub ^UNDEFINEDPUNCTUATION) nie wystąpią w przypadku dobrze sformułowanych danych wejściowych, a zatem zachowanie jest niezdefiniowane.

Zespół programistów informuje o następujących kwestiach:

  • Projekt jest napisany w języku [Twój język tutaj] i powinien być możliwie jak najkrótszy, aby zajmował jak najmniej miejsca, gdy jest to aplikacja na Androida / iPhone'a. Próbujesz wyjaśnić, że nie tak działa tworzenie aplikacji, ale oni nie słuchają. Ale hej, co za zbieg okoliczności! Jesteś niesamowitym golfistą w [swoim języku tutaj] !

  • Aplikacja nie będzie miała żadnych uprawnień dostępu do sieci i nie będzie żadnych bibliotek, które dokonałyby tego formatowania. Prawdopodobnie możesz przekonać kierownika zespołu, aby zezwolił ci na bibliotekę wyrażeń regularnych, jeśli istnieje ona dla twojego języka, ale jeśli uważasz, że potrzebujesz.

  • Obsługa zagnieżdżonych cytatów, które prawidłowo używają podwójnych / pojedynczych cudzysłowów, jest planowana w późniejszej wersji aplikacji, ale nie w wersji, nad którą pracujesz teraz, więc nie martw się o to.

  • Kierownictwo jest wielkim fanem rozwoju opartego na testach, dlatego zespół deweloperów zlecił już pewnej nieszczęsnej małpce klawiaturowej napisanie testów dla twojej części programu: (dodano nowe wiersze dla czytelności, traktuj je jako spacje)

    Wejście:

    hello ^COMMA   world ^BANG
    

    Wynik:

    Hello, world!
    

    Wejście:

    once upon a time ^COMMA there was a horse ^PERIOD that horse cost me $50
    ^PERIOD ^OPENQUOTE eat your stupid oats ^COMMA already ^BANG ^CLOSEQUOTE
    I told the horse ^PERIOD the horse neighed back ^OPENQUOTE no ^CLOSEQUOTE
    and died ^PERIOD THE END
    

    Wynik:

    Once upon a time, there was a horse. That horse cost me $50. "Eat your
    stupid oats, already!" I told the horse. The horse neighed back, "No,"
    and died. THE END
    

    Wejście:

    begin a ^PERIOD b ^COMMA c ^COLON d ^SEMICOLON e ^BANG f ^HYPHEN g ^DASH h
    ^EMDASH i ^OPENQUOTE j ^PERIOD ^OPENQUOTE k ^SEMICOLON ^OPENQUOTE l
    ^CLOSEQUOTE m ^BANG ^CLOSEQUOTE n ^PERIOD 0x6C6F6C end
    

    Wynik:

    Begin a. B, c: d; e! F-g - h--i, "j. "K; "l," m!" N. 0x6C6F6C end
    

To jest golf golfowy: wygrywa najniższy wynik. Możesz napisać funkcję o jednym argumencie łańcuchowym lub program odczytujący ze STDIN i zapisujący do STDOUT.

algorytmshark
źródło
Co jeśli chcę użyć javascript? Nie ma w nim standardowego wejścia. Czy mogę użyć prompt()?
nicael
@nicael OP wspomina o użyciu jednego argumentu ciągu, więc dla mojego przykładu JS właśnie stworzyłem funkcję, która przyjmuje jeden argument i założyłem, że argumentem jest ciąg słów podobny do STDIN
Eric Lagergren
1
Zastanawiam się, czy istnieje esolang o nazwie „[twój język tutaj]”
Akangka,

Odpowiedzi:

4

JavaScript: 653 611 547 514 487 bajtów

O mój Boże. Brendan Eich Przykro mi z tego powodu.

PS: Dodałem białe znaki dla czytelności, ale usunięcie wszystkich dozwolonych białych znaków powoduje wyświetlenie liczby bajtów.

Teoretycznie mógłbym skrócić niektóre części -e-do czegoś podobnego -elub -e, ale może to powodować problem, jeśli poprzednie słowo kończy się na, lub następne słowo zaczyna się na literę „e” (lub dowolne słowo, którego zdecyduję się użyć). Przypuszczam, że mógłbym użyć znaku ASCII. Zajrzę do tego.

487 FF22 + Tylko

R = "replace", C = "charAt", U = "toUpperCase";
alert(a[R](/\^((COMMA)|(SEMICOLON)|(COLON)|(PERIOD)|(BANG)|(DASH)|(HYPHEN)|(EMDASH)|(OPENQUOTE)|(CLOSEQUOTE))/g, ((m, _, a, b, c, d, e, f, g, h, i, j) => a ? "," : b ? ";" : c ? ":" : d ? "." : e ? "!" : f ? "-" : g ? "-h-" : h ? "-e-" : i ? ' "' : '" '))[R](/\s((\.)|(\!)|(\,)|(\;)|(\:)|(\-\h\-\s)|(\-\e\-\s))/g, ((k, l, v, n, o, p, q, r, s) => v ? "." : n ? "!" : o ? "," : p ? ";" : q ? ":" : r ? "-" : "--"))[R](/[^!,"'.]\"\s/g, '"')[R](/.+?[\.\?\!](\s|$)/g, (t => t[C](0)[U]() + t.substr(1)))[R](/\"[a-z]/g, (u => u[C](0) + u[C](1)[U]())))

514 FF22 + Tylko

alert(function(z) {
    R = "replace", C = "charAt", U = "toUpperCase";
    return z[R](/\^((COMMA)|(SEMICOLON)|(COLON)|(PERIOD)|(BANG)|(DASH)|(HYPHEN)|(EMDASH)|(OPENQUOTE)|(CLOSEQUOTE))/g, ((m, _, a, b, c, d, e, f, g, h, i, j) => a ? "," : b ? ";" : c ? ":" : d ? "." : e ? "!" : f ? "-" : g ? "-h-" : h ? "-e-" : i ? ' "' : '" '))[R](/\s+((\.)|(\!)|(\,)|(\;)|(\:)|(\-\h\-\s+)|(\-\e\-\s+))/g, ((k, l, v, n, o, p, q, r, s) => v ? "." : n ? "!" : o ? "," : p ? ";" : q ? ":" : r ? "-" : "--"))[R](/[^!,"'.]\"\s/g, '"')[R](/.+?[\.\?\!](\s+|$)/g, (t => t[C](0)[U]() + t.substr(1)))[R](/\"[a-z]/g, (u => u[C](0) + u[C](1)[U]()))
}(a))

547 FF22 + Tylko

alert(function(z) {
    R = "replace", C = "charAt", U = "toUpperCase";
    return z[R](/\^((COMMA)|(SEMICOLON)|(COLON)|(PERIOD)|(BANG)|(DASH)|(HYPHEN)|(EMDASH)|(OPENQUOTE)|(CLOSEQUOTE))/g, ((m, _, a, b, c, d, e, f, g, h, i, j) => a ? "," : b ? ";" : c ? ":" : d ? "." : e ? "!" : f ? "-" : g ? "-h-" : h ? "-e-" : i ? ' "' : '" '))[R](/\s+((\.)|(\!)|(\,)|(\;)|(\:)|(\-\h\-\s+)|(\-\e\-\s+))/g, ((xx, __, k, l, m, n, o, p, q) => k ? "." : l ? "!" : m ? "," : n ? ";" : o ? ":" : p ? "-" : "--"))[R](/[^!,"'.]\"\s/g, '"')[R](/.+?[\.\?\!](\s+|$)/g, function(r) {
        return r[C](0)[U]() + r.substr(1)
    })[R](/\"[a-z]/g, function(s) {
        return s[C](0) + s[C](1)[U]()
    })
}(a))

Tylko 611 FF 22+

alert(function(c) {
    return c.replace(/\^((COMMA)|(SEMICOLON)|(COLON)|(PERIOD)|(BANG)|(DASH)|(HYPHEN)|(EMDASH)|(OPENQUOTE)|(CLOSEQUOTE))/g, ((x, _, a, b, c, d, e, f, g, h, i) = > a ? "," : b ? ";" : c ? ":" : d ? "." : e ? "!" : f ? "-" : g ? "-h-" : h ? "-e-" : i ? ' "' : '" ')).replace(/\s+\./g, ".").replace(/\s+\!/g, "!").replace(/\s+\,/g, ",").replace(/\s+\;/g, ";").replace(/\s+\:/g, ":").replace(/\s\-\h\-\s/g, "-").replace(/[^!,"'.]\"\s/g, '"').replace(/\s+\-\e-\s+/g, "--").replace(/.+?[\.\?\!](\s+|$)/g, function(b) {
        return b.charAt(0).toUpperCase() + b.substr(1)
    }).replace(/\"[a-z]/g, function(b) {
        return b.charAt(0) + b.charAt(1).toUpperCase()
    })
}(a))

653 przeglądarka internetowa

alert(function(c) {
    return c.replace(/\^COMMA/g, ",").replace(/\^SEMICOLON/g, ";").replace(/\^COLON/g, ":").replace(/\^PERIOD/g, ".").replace(/\^BANG/g, "!").replace(/\^DASH/g, "-").replace(/\^HYPHEN/g, "h-h").replace(/\^EMDASH/g, "-e-").replace(/\^OPENQUOTE/g, ' "').replace(/\^CLOSEQUOTE/g, '" ').replace(/\s+\./g, ".").replace(/\s+\!/g, "!").replace(/\s+\,/g, ",").replace(/\s+\;/g, ";").replace(/\s+\:/g, ":").replace(/\s\h\-\h\s/g, "-").replace(/[^!,"'.]\"\s/g, '"').replace(/\s+\-\e-\s+/g, "--").replace(/.+?[\.\?\!](\s|$)/g, function(b) {
        return b.charAt(0).toUpperCase() + b.substr(1)
    }).replace(/\"[a-z]/g, function(b) {
        return b.charAt(0) + b.charAt(1).toUpperCase()
    })
}(a))

Jak to działa:

https://gist.github.com/ericlagergren/1a61b5d772ae49ab3aea

JSFiddle (dla 653-bajtowego rozwiązania dla różnych przeglądarek)

JSFiddle (dla 595 FF 22+ tylko roztwór)

JSFiddle (dla 547 FF 22+ tylko roztwór)

JSFiddle (dla 514 FF 22+ tylko roztwór)

JSFiddle ( tylko rozwiązanie 487 FF 22+ )

To pierwszy raz, kiedy muszę napisać JS, który używa więcej niż jednego wyrażenia regularnego, i zwykle mój wyrażenie regularne jest predefiniowane.

Będę nadal golić bajty, jak tylko mogę.

Eric Lagergren
źródło
Możesz skrócić swoje pierwsze zastępstwa w ten sposób: c.replace(/\^((COMMA)|(SEMICOLON)|(COLON)|(PERIOD)|(BANG))/g,(m,_,a,b,c,d,e)=>a?',':b?';':c?':':d?'.':'!'))... i tak dalej. Strzałka sintax jest krótka, ale nawet „funkcja” powinna zapisywać te same znaki
edc65
Masz rację. Testowałem wyrażenie regularne w Chrome i nie obsługuje grubych strzał. Pracuję teraz nad tym, aby to wyjaśnić za pomocą FF, ale nienawidzę tego, jak regexps tak naprawdę nie mają operatora „i”, tak jak robią to „lub”. @ edc65
Eric Lagergren
@ edc65, więc myślę, że będę musiał użyć dwóch =>s, aby go uruchomić, ale użycie strzałek pozwoliło mi zaoszczędzić 40 bajtów!
Eric Lagergren
Zamień zamień na R = „replace” ... [R] ;-)
edc65
Właśnie to zrobiłem :) Zrobiłem to do 563 @ edc65
Eric Lagergren
1

PHP, 412 bajtów

(Ungolfed tutaj dla przejrzystości; zobacz ideone dla wersji golfowej .)

Funkcja preg_replace () PHP akceptuje argumenty tablicowe, co jest tu bardzo przydatne. Myślę, że poniższy kod robi wszystko, co jest wymagane. Przechodzi co najmniej wszystkie przypadki testowe.

function x($s) {
    $r='preg_replace';
    $s=$r('/ +/',' ',$s);
    $s=$r(array('/ \^COMMA/','/ \^COLON/','/ \^SEMICOLON/','/ \^PERIOD/','/ \^BANG/',
                '/\^DASH/','/ \^HYPHEN /','/ \^EMDASH /','/\^OPENQUOTE /','/ \^CLOSEQUOTE/'),
          array(',',':',';','.','!','-','-','--','"',',"'),
          $s);
    $s=$r('/(^\W*\w|([\.!]| ")\W+\w)/e','strtoupper("$0")',$s);
    $s=$r('/([,\.!]),/','\1',$s);
    $s=$r('/(\w)( "\w)/e','"$1,".strtoupper("$2")',$s);
    echo $s;
}
r3mainer
źródło
Działa świetnie! ideone.com/AYtTiI Chociaż jestem zdezorientowany, czy powinniśmy mieć przecinki przed otwartymi cytatami? Ponieważ gramatycznie znaki cudzysłowu są czymś więcej niż mową, ale tylko mowa ma przecinek przed cudzysłowem. Zakładałem, że skoro istnieje COMMA,
pozwolimy