Решение задачи однострочником на perl. С объяснениями Ж:-)


ramok аватар

ramok - Posted on 23 Июль 2007

На сайте http://www.esci.ru/kcc2/kcc2_t.php есть любопытные задачки,
интересные для разминки и обучения Ж:-)

Процитирую одну, немного подправив:

Цитата:

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

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

input:
A beautiful new world. Come.
output:
Emoc. Dlrow wen lufituaeb a.

Сразу дам одно из решений, что бы напугать Ж:-) Решение

echo "A beautiful new world. Come." |\
  perl -pe '$_=lc;s/.\./uc $&/ge;$_=reverse;s/ \./. /g;s/^\W+(.*)/$1.\n/'
Emoc. Dlrow wen lufituaeb a.

И попробуем во всем этом разобраться..

Объяснение:

0. Ключи запуска perl


Ключик -p делает из perl продвинутый аналог sed.
И обозначает что perl будет считывать построчно все что ему передают
на стандартный ввод, заносить в переменную $_ и применять к этой строке
программу. И так строка за строкой.

Итак в переменной $_ находится строка "A beautiful new world. Come.\n".
\n так символически обычно обозначается знак перевода строки.

1. Переводим все в нижний регистр

$_=lc

Функция lc (low case) как раз этим занимается. Если не дать функции
lc никакого параметра, то она автоматически возьмет $_. Результат попадет в $_.
до: $_ = "A beautiful new world. Come.\n"
после: $_ = "a beautiful new world. come.\n"
литература: http://perldoc.perl.org/functions/lc.html

2. Все буквы справа от которых есть точка, увеличиваем

s/.\./uc $&/ge

s/// это оператор замены. s переводится как substitutions(замена).
Символ / разделитель. "s/было/стало/" заменит слово "было" в $_ на слово
"стало". $& это переменная в которой находится строка которую нашли.

Ищем по регулярному выражению ".\.", что обозначает "любой символ,
и следующая за ним точка". Из найденного составляем команду perl

uc $найденная_строка

Функция uc (upper case) аналог фунции lc.
Вызваем эту команду (флажок e, после s///). Эту операцию повторяем для
всех найденых точек (флажок g, после s///).

до: $_ = "a beautiful new world. come.\n"
после: $_ = "a beautiful new worlD. comE.\n"
литература: http://perldoc.perl.org/perlre.html
http://perldoc.perl.org/functions/s.html
http://perldoc.perl.org/functions/uc.html

3. Переворачиваем строку

$_=reverse

Если не дать функции reverse никакого параметра, то она автоматически возьмет $_.

до: $_ = "a beautiful new worlD. Come.\n"
после: $_ = "\n.Emoc .Dlrow wen lufituaeb a"
литература: http://perldoc.perl.org/functions/reverse.html

4.Меняем точку и пробел местами по всей строке

s/ \./. /g

Ищем регесп " \." что значит "пробел и следующая за ним точка",
и меняем ее на ". ". Выполняем это по всей строке (флажок g, после s///).

до : $_ = "\n.Emoc .Dlrow wen lufituaeb a"
после: $_ = "\n.Emoc. Dlrow wen lufituaeb a"

литература: http://perldoc.perl.org/perlre.html
http://perldoc.perl.org/functions/s.html

5. Перевод строки и точку в начале строки переносим в конец строки

s/^\W+(.*)/$1.\n/

^ - в данном случае это обозначает "начало строки"
\W - "не слово". То есть пробелы, переводы строки, знаки пунктуации и прочее.
Мы надеемся отловить этим знак перевода строки и точку в начале строки.
+ - обозначает что \W может быть один или больше.
(.*) - буквально обозначает "любой символ повторенный от 0 до бесконечности раз".
Скобки () обозначают что в переменную $1 попадет значение всей строки.

до: $_ = "\n.Emoc. Dlrow wen lufituaeb a"
после: $_ = "Emoc. Dlrow wen lufituaeb a.\n"

литература: http://perldoc.perl.org/perlre.html
http://perldoc.perl.org/functions/s.html

Все! Ж:-)

Проверим что будет работать и с большим кол-вом слов:

$ echo "A beautiful new world. Come. Now." |\
  perl -pe '$_=lc;s/.\./uc $&/ge;$_=reverse;s/ \./. /g;s/^\W+(.*)/$1.\n/'
Won. Emoc. Dlrow wen lufituaeb a.
0
Ваша оценка: Ничего

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

p.s.: сотона не есть плюс =/

одно другому не мешает Ж;-)
PS
тот о котором ты подумал пишется через два 'a' Ж:-)
--
Signature invent in progress 24% ##........