Разгребал сегодня RSS-читалку и наткнулся на объявление о проведении очередного конкурса по ФП от Романа Душкина . Задачка на этот раз оказалась довольно простой. Вот я и подумал, а почему бы мне не воспользоваться случаем и не попрактиковаться лишний раз в программировании на Scala ?

Задача формулируется так. Дан большой файл из ноликов и единичек и способ кодирования цифр при помощи матриц 3×5. Нужно взять входной файл и вывести координаты спрятанных в нем цифр, а также распознать эти самые цифры. Поколдовав от силы минут 20 в IntelliJ IDEA у меня получилось такое решение:

import scala. io . Source
import java. io . File

object FPPochtaRossii extends App {
if ( args. isEmpty ) {
println ( «Usage: fp-pochta-rossii matrix.txt» )
System. exit ( 1 )
}

val inputFile = new File ( args ( 0 ) )
val lines = Source. fromFile ( inputFile ) . getLines ( ) . toArray
val height = lines. length
val width = lines ( 0 ) . length

for ( x < 0 until width — 3 )
for ( y < 0 until height — 5 ) {
val image = for ( ln < 0 until 5 )
yield lines ( y + ln ) . substring ( x, x+ 3 )
recognize ( image ) match {
case Some ( i ) => println ( s «x = ${x}, y = ${y}, number = ${i}» )
case None => ; // do nothing
}
}

def recognize ( lines : Seq [ String ] ) : Option [ Int ] = {
lines match {
case Seq ( «111» , «101» , «101» , «101» , «111» ) => Some ( 0 )
case Seq ( «110» , «010» , «010» , «010» , «111» ) => Some ( 1 )
case Seq ( «111» , «001» , «111» , «100» , «111» ) => Some ( 2 )
case Seq ( «111» , «001» , «111» , «001» , «111» ) => Some ( 3 )
case Seq ( «101» , «101» , «111» , «001» , «001» ) => Some ( 4 )
case Seq ( «111» , «100» , «111» , «001» , «111» ) => Some ( 5 )
case Seq ( «111» , «100» , «111» , «101» , «111» ) => Some ( 6 )
case Seq ( «111» , «001» , «011» , «010» , «010» ) => Some ( 7 )
case Seq ( «111» , «101» , «111» , «101» , «111» ) => Some ( 8 )
case Seq ( «111» , «101» , «111» , «001» , «111» ) => Some ( 9 )
case _ => None
}
}
}

Компиляция и запуск:

scalac proc.scala
java -cp . FPPochtaRossii matrix.txt

Решение, как видите, «в лоб». Уж не знаю, насколько хорошо оно будет работать на больший файлах, но на моем ноутике для заданного в условиях файла программа отрабатывает за 0.4 секунды с учетом накладных расходов на запуск JVM. Очевидно также, что задача прекрасно распараллеливается.

Вот что здорово в Scala — говнекается быстро, код получается довольно сносным, и работает он при этом достаточно быстро. Синтаксис языка, даже если ты его толком не помнишь, довольно очевиден. И, надо отметить, наличие нормальной IDE вовсе не препятствует разработке , а только всячески помогает ей. Ведь по сути IDE — это такой мощный текстовый редактор с парой крутых фичей, которых нет в Vim. Например, подсказками по аргументам функций, подсветкой синтаксических ошибок еще перед компиляцией, или рефакторингами типа переименования переменной всюду, где она встречается. При программировании на Haskell, к примеру, мне действительно не хватает нормальной IDE.

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

EnglishRussianUkrainian