Надеюсь, группа жива.
Преамбула
Время от времени, чтобы "не загрубеть" от технологий, которые ты уже знаешь более-менее, я изучаю другие языки программирования.
Технология изучения у меня простая: читаю примерно половину книги по языку, чтобы понять основы, далее перехожу к практике.
В качестве практики я прорешиваю самые простые задачи на codeforces и project-euler (далее PE), в случае с clojure первый ресурс, к сожалению, не подходит.
К делу
Наверное, у каждого языка можно выделить некоторые правила, как на нем писать надо, а как не надо, так называемое %language%-way
Например: в Ruby, в 90% случаев лучше использовать итераторы вместо циклов, а без цикла for вы совершенно точно сможете обойтись.
Сейчас подобную картину я пытаюсь уложить в голове по поводу clojure.
С циклами тут все туго, да еще и новый функциональный подход... Разобраться в erlang и ocaml (кроме типов), признаюсь, мне было проще.
Ниже я приведу ссылки на решения и некоторые свои комментарии. Если вы видите как можно было решить лучше именно с точки зрения
языка, а не алгоритма в целом (так как я ставлю своей задачей научится программировать на языке, а не написать самое быстрое решение), то
буду рад услышать комментарии.
Почитав про язык, я подумал, что очень хорошо использовать ленивые последовательности везде, где это возможно и, в результате, получилось:
(Просуммировать все делимые 3 или 5 ниже 1000)
Я вижу этот код так: делаем ленивую последовательность и добавляем в нее числа пока очередное число не превысит 1000, после этого суммируем.
Правильно ли я понимаю, что после суммирования последовательность соберется сборщиком?
(Просуммировать все четные числа фибоначчи до миллиона)
(Найти самый большой простой делитель числа)
Правильно ли я понимаю, что тут будет хвостовая рекурсия?
(Найти больший палиндром среди произведения всех трехзначных чисел)
Нормально ли использовать так цикл for? Можно ли написать более оптимально функцию palindrom?
Найти разность между квадратом суммы и суммой квадратов
Ну тут уж совсем просто, можно ли еще проще?
Самая длинная по коду задача, скажем, суть ее заключается в умении переводить из римских в арабские и наоборот:
Тут совершенно точно, можно сделать лучше. Особенно мне не нравится строчка "(> arabic 999) (str (apply str (repeat (quot arabic 1000) "M")) (to-roman (rem arabic 1000)))".
С удовольствием послушаю ваши идеи, как сделать код более clojure-way.
Спасибо!