├── .gitignore ├── Makefile ├── input.txt ├── jbuild ├── icecreamparlor.opam ├── README.md └── icecreamparlor.ml /.gitignore: -------------------------------------------------------------------------------- 1 | /_opam/ 2 | /_build/ 3 | .merlin 4 | *.install 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all: 3 | jbuilder build --dev 4 | -------------------------------------------------------------------------------- /input.txt: -------------------------------------------------------------------------------- 1 | 2 2 | 4 3 | 5 4 | 1 4 5 3 2 5 | 4 6 | 4 7 | 2 2 4 3 8 | -------------------------------------------------------------------------------- /jbuild: -------------------------------------------------------------------------------- 1 | (executable 2 | ((name icecreamparlor) 3 | (public_name icecreamparlor) 4 | (libraries (base stdio)))) 5 | -------------------------------------------------------------------------------- /icecreamparlor.opam: -------------------------------------------------------------------------------- 1 | opam-version: "1.2" 2 | maintainer: "Marek Kubica " 3 | authors: [ "Marek Kubica " ] 4 | build: [["jbuilder" "build" "-p" name "-j" jobs]] 5 | depends: [ 6 | "jbuilder" {build} 7 | "base" {>= "v0.11" & < "v0.12"} 8 | "stdio" {>= "v0.11" & < "v0.12"} 9 | ] 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Ice cream parlor problem 2 | ======================== 3 | 4 | OCaml solution to [Ice cream parlor 5 | problem](https://www.hackerrank.com/challenges/ctci-ice-cream-parlor/problem) 6 | on Hackerrank. 7 | 8 | Usage 9 | ----- 10 | 11 | Create a local OPAM 2 switch, compile and run with jbuilder: 12 | 13 | ```sh 14 | opam switch create ./ ocaml-base-compiler.4.06.1 15 | jbuilder exec icecreamparlor < input.txt 16 | ``` 17 | -------------------------------------------------------------------------------- /icecreamparlor.ml: -------------------------------------------------------------------------------- 1 | open Base 2 | open Stdio 3 | 4 | type t = { 5 | costs: (int * int) list; 6 | costs_array: (int * int) array; 7 | money: int; 8 | } 9 | 10 | let read_input () = 11 | let rev_compare (x, _index) (y, _index) = 12 | Int.compare y x 13 | in 14 | match In_channel.input_line In_channel.stdin with 15 | | Some line -> 16 | Int.of_string line 17 | |> List.init ~f:ignore 18 | |> List.map ~f:(fun () -> 19 | match In_channel.input_line In_channel.stdin, In_channel.input_line In_channel.stdin, In_channel.input_line In_channel.stdin with 20 | | Some money, Some array_size, Some costs -> 21 | let money = Int.of_string money in 22 | let len = Int.of_string array_size in 23 | let costs_array = Array.create ~len (0, 0) in 24 | let costs = 25 | costs 26 | |> String.strip 27 | |> String.split ~on:' ' 28 | |> List.mapi ~f:(fun index v -> 29 | let price = Int.of_string v in 30 | costs_array.(index) <- (price, index); 31 | (price, index)) 32 | |> List.sort ~compare:rev_compare 33 | in 34 | Array.sort costs_array ~compare:(fun (price, _) (price', _) -> Int.compare price price'); 35 | { money; costs; costs_array } 36 | | _ -> failwith "Invalid format") 37 | | None -> failwith "No num" 38 | 39 | let array_get array index = 40 | match array.(index) with 41 | | v -> Some v 42 | | exception Invalid_argument _ -> None 43 | 44 | let pick_second 45 | : int -> int -> (int * int) array -> int option 46 | = fun already_used_index remaining costs_array -> 47 | match Array.binary_search costs_array ~compare:(fun (price, _) key -> Int.compare price key) `First_equal_to remaining with 48 | | None -> None 49 | | Some index -> 50 | match index = already_used_index with 51 | | false -> 52 | let (_, original_index) = costs_array.(index) in 53 | Some original_index 54 | | true -> 55 | match array_get costs_array (Int.succ index) with 56 | | Some (value, original_index) when value = remaining -> Some original_index 57 | | _ -> None 58 | 59 | let rec pick money costs_array = function 60 | | [] -> None 61 | | (price, _) :: prices when price > money -> 62 | pick money costs_array prices 63 | | (price, index) :: prices -> 64 | let remaining = money - price in 65 | match pick_second index remaining costs_array with 66 | | None -> pick money costs_array prices 67 | | Some second_index -> 68 | match index < second_index with 69 | | true -> Some (index, second_index) 70 | | false -> Some (second_index, index) 71 | 72 | let solve { money; costs; costs_array } = 73 | pick money costs_array costs 74 | 75 | let print_solution = function 76 | | None -> print_endline "No solution" 77 | | Some (smaller, larger) -> Caml.Printf.printf "%d %d\n" (smaller + 1) (larger + 1) 78 | 79 | let main () = 80 | read_input () 81 | |> List.map ~f:solve 82 | |> List.iter ~f:print_solution 83 | 84 | let () = 85 | main () 86 | --------------------------------------------------------------------------------