Разработка на коленке

"тут должна быть красивая цитата о программировании"

How to split string in Ocaml

2016-07-15 19:27

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

Тут стоит сказать, что стандартная библиотека OCaml очень маленькая, и писать код, используя только её, никому в голову не приходит. Одна из популярных - переписанная Core программистами из jane street. Этим OCaml сильно отличается от питона, у которого стандартная библиотека просто огромна, а на codingame сверху установлен numpy.

В задаче про поиск температуры, ближайшей к нулю - Temperatures, нужно было взять строку из stdin и разделить её на числа. Вот только в стандартной библиотеке такого функционала нет. То, что там нет Core меня расстроило. Первой мыслью было отказаться от OCaml и либо перейти на Python3 либо вообще забросить codingame. Второй мыслью было, сделать необходимый функционал самому, задача не особо трудная.

Сделал.

Само собой, что такой код в реальный продакшн я бы не послал, хотя бы из-за того, что у меня списки конкатенируются, что каждый раз создаёт новые. И не факт, что функция хорошо будет работать на граничных случаях или корректно обработает два разделителя подряд. Однако мне она позволила решить задачу, а на игровой площадке мне пока большего не нужно.

let split delimiter str =
    let max = String.length str in

    let rec _split str i lst =
        if i < max then
            let ch = String.get str i in
            if ch = delimiter then
                (String.concat "" lst) :: (_split str (i + 1) [])
            else
                _split str (i + 1) (lst @ [String.make 1 ch])
        else
            [String.concat "" lst]
    in
    _split str 0 []
;;

Публикую только функцию, а не всё решение. Вроде по правилам решение публиковать нельзя.

P.S. После публикации посмотрел решения других людей и увидел использование Scanf.scanf, чтобы получить список чисел.

let get_int () = Scanf.scanf " %d" (fun x -> x);;


let rec get_ints = function
    | 0 -> []
    | n -> get_int () :: get_ints (n - 1)
;;


let () =
    get_ints 3 |> List.map string_of_int
               |> String.concat " "
               |> print_endline
;;

Это то, чего я не смог сделать сам, хотя пробовал несколько способов. Кстати, этот код сохраняет список в обратном порядке, что стоит помнить, если порядок имеет значение.

Жаль, что с каждым решённым заданием, список чужих решений всё короче (в этот раз - 9). Интересно, как много решений на Haskell?