Применять английские правила пунктуации

11

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

Руководство на самом деле не доверяет вам всю мощь проекта - вы, к сожалению, весь день сидите и играете в гольф, а не выполняете свою работу, поэтому они просто дают вам действительно простую задачу: Предложение со вставленной пунктуацией в правильно отформатированном предложении, где «правильно отформатированный» определяется ниже.

  1. Предложение - это строка ввода. Слово - это группа случайных непробельных символов. Пунктуация - это Слово, первым символом которого является ^.

  2. Слово пишется с большой буквы, если первая буква Слова не строчная (слова с заглавной буквы соответствуют регулярному выражению /[^a-z].*/).

  3. Первое Слово Предложения должно быть написано заглавными буквами.

  4. A ^COMMAявляется запятой ,и имеет пробел после, но не перед ним. aaa ^COMMA bbbстановится aaa, bbb.

  5. А ^COLONэто запятая, которая выглядит так :.

  6. А ^SEMICOLONэто запятая, которая выглядит так ;.

  7. А ^PERIODэто запятая, которая выглядит так .. Слово после a ^PERIODдолжно быть написано заглавными буквами.

  8. А ^BANGэто период, который выглядит так !.

  9. A ^DASHявляется символом тире -и имеет пробел как перед, так и после.

  10. A ^HYPHENтакже является символом тире, -но не имеет пробела после или перед ним.

  11. Это ^EMDASHдефис (не тире!), Который пишется --.

  12. An ^OPENQUOTEявляется символом кавычки, "который имеет пробел перед, но не после. Слово, следующее за, ^OPENQUOTEдолжно быть написано заглавными буквами. Если ^OPENQUOTEперед словом стоит слово, которое не является пунктуацией, добавьте ^COMMAмежду этим словом и ^OPENQUOTE. Если ^OPENQUOTEперед точкой стоит пунктуация, в которой следующее слово пишется с заглавной буквы, оно переходит ^OPENQUOTEк следующему слову.

  13. A ^CLOSEQUOTE- орграф ,", у которого есть пробел после, но не перед ним. Если ^CLOSEQUOTEпредшествует ^COMMA, ^PERIODили ^BANG, что пунктуации исчезает и ^CLOSEQUOTEпишется ,", ."или !"соответственно. Если исчезающая пунктуация указывает на заглавную букву, эта заглавная буква должна все еще встречаться в следующем доступном слове.

  14. Начальные или конечные пробелы в полном конечном результате должны быть удалены, и любая строка из двух или более пробелов в строке должна быть свернута в один пробел.

  15. Любой случай, не описанный выше (например, ^COMMA ^COMMAили ^SEMICOLON ^CLOSEQUOTEили ^UNDEFINEDPUNCTUATION), не будет иметь место в правильно сформированном вводе и, таким образом, будет неопределенным поведением.

Команда разработчиков сообщает вам следующее:

  • Проект написан на языке [ваш язык здесь] и должен быть максимально коротким, чтобы занимать как можно меньше места, когда это приложение для Android / iPhone. Вы пытаетесь объяснить, что не работает разработка приложений, но они не слушают. Но эй, какое совпадение! Вы удивительный игрок в гольф на [ваш язык здесь] !

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

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

  • Руководство является большим поклонником разработки, основанной на тестировании, и поэтому команда разработчиков уже имела несколько несчастных клавиатурных обезьян, написавших некоторые тесты для вашей части программы: (добавлены новые строки для удобства чтения, рассматривайте их как пробелы)

    Входные данные:

    hello ^COMMA   world ^BANG
    

    Выход:

    Hello, world!
    

    Входные данные:

    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
    

    Выход:

    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
    

    Входные данные:

    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
    

    Выход:

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

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

algorithmshark
источник
Что делать, если я хочу использовать JavaScript? В нем нет стандартного ввода. Могу ли я использовать prompt()?
Никель
В @nicael OP упоминается использование одного строкового аргумента, поэтому для моего примера JS я просто создал функцию, которая принимает один аргумент, и предположил, что аргумент - это строка слов, аналогичная STDIN
Эрик Лагергрен,
1
Интересно, есть ли esolang по имени «[ваш язык здесь]»
Akangka

Ответы:

4

JavaScript: 653 611 547 514 487 байт

О, черт возьми. Брендан Эйч, мне так жаль.

PS: я добавил пробел для удобства чтения, но удаление всех допустимых пробелов приводит к количеству байтов в списке.

Теоретически я мог бы сократить некоторые части, например, -e-до чего-то вроде -eили -e, но это может вызвать проблему, если предыдущее слово заканчивается или следующее слово начинается с буквы «е» (или любого другого слова, которое я решу использовать). Я полагаю, я мог бы использовать символ ASCII. Я посмотрю на это.

Только 487 FF22 +

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 +

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 +

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

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 кросс-браузер

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

Как это работает:

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

JSFiddle (для 653-байтового кросс-браузерного решения)

JSFiddle (для 595 FF 22+ только раствор)

JSFiddle ( только для решения 547 FF 22+ )

JSFiddle ( только для решения 514 FF 22+ )

JSFiddle ( только для решения 487 FF 22+ )

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

Я буду продолжать сбрить байты настолько, насколько смогу.

Эрик Лагергрен
источник
Вы можете сократить свои первые замены следующим образом: c.replace(/\^((COMMA)|(SEMICOLON)|(COLON)|(PERIOD)|(BANG))/g,(m,_,a,b,c,d,e)=>a?',':b?';':c?':':d?'.':'!'))... и так далее. Синтаксис стрелки короткий, но даже «функция» должна сохранять те же символы
edc65
Вы правы. Я протестировал свое регулярное выражение с Chrome, и оно не поддерживает жирные стрелки. Я сейчас работаю над тем, чтобы уладить это с помощью FF, но я ненавижу, что регулярные выражения на самом деле не имеют операторов "и", как они делают "или". @ edc65
Эрик Лагергрен
@ edc65, так что я думаю, что мне придется использовать два =>s, чтобы заставить его работать, но использование стрелок сэкономило мне 40 байт!
Эрик Лагергрен
Заменить заменить на R = 'replace' ... [R] ;-)
edc65
Просто сделал это :) Получил до 563 @ edc65
Эрик Лагергрен
1

PHP, 412 байт

(Разгаданный здесь для ясности; см. Ideone для версии для гольфа .)

Функция PHP preg_replace () будет принимать аргументы массива, что очень полезно здесь. Я думаю, что следующий код делает все, что требуется. Он проходит все тестовые случаи как минимум.

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
источник
Работает отлично! ideone.com/AYtTiI Хотя меня смущает то, что мы должны иметь запятые перед открытыми кавычками? Потому что, говоря грамматически, кавычки - это не просто речь, а только кавычка перед кавычками. Я предположил, что, поскольку была ^ COMMA, мы позволили бы пользователю вводить запятую
Эрик Лагергрен