Юлия, 90 знаков
s->all(cumsum(map(i->i∈"!|.\":"?-1:i∈"()_@\$&",mapfoldl(collect,hcat,split(s,"
")))').>-1)
В отличие от исходного решения (ниже), здесь используется математика для определения решения. mapfoldl(collect,hcat,split(s,"\n"))
(написано выше с \n
заменой фактической новой строки для сохранения символов) преобразует строку в 2d массив символов. map(i->i∈"!|.\":"?-1:i∈"()_@\$&",...)
создает массив чисел, с 1, если символ является облаком, -1, если символ дождь, и 0 в противном случае.
cumsum(...')
вычисляет кумулятивные суммы строк (обычно записывается cumsum(...,2)
, но, поскольку с этого момента мы не заботимся об ориентации, транспонирование стоит только один символ), а затем all(... .>-1)
проверяет наличие отрицательного числа - отрицания будут появляться только в том случае, если символ дождя появляется без предшествующего облачного персонажа.
Юлия, 139 136 символов
s->(t=join(mapfoldl(i->split(i,""),.*,split(s,"
")),"
");while t!=(t=replace(t,r"[()_@$&](.*?)[!|.\":]",s"\g<1>"))end;∩("!|.\":",t)==[])
Эта функция сначала транспонирует текст так, что строки становятся столбцами, и наоборот. Обратите внимание, что новые строки присутствуют в коде в виде реальных новых строк, чтобы сохранить один символ на экземпляр.
Затем функция итеративно заменяет пары облако / капля пробелами, и как только все такие пары удаляются, она возвращает true, если есть какие-либо оставшиеся капли, и false в противном случае.
r"[()_@$&](.*?)[!|.\":]"
- это регулярное выражение, которое будет лениво сопоставлять пары облако / капелька, а группа 1 содержит все, что находится между облаком и каплей. Затем s"\g<1>"
говорит ему удалить совпадающее облако и капли, но держать материал между ними (необходимо, поскольку он может содержать облака) - \g<1>
это то, что было найдено в группе 1 регулярного выражения. ∩("!|.\":",t)==[]
сгенерирует пересечение символов капли с последней строкой, и если она пуста, то ни один из символов капли не присутствует, и идет дождь.