use "files" use "format" use "itertools" primitive Fuel // calculate the amount of fuel needed fun calc(x: U64) : U64 => (x / 3) - 2 // calculate the amount of fuel needed, naively recursively taking //in account the weight of the fuel fun calc_recursive(x: U64) : U64 => let weight = calc(x) if weight > 6 then weight + calc_recursive(weight) else weight end actor Main new create(env: Env) => // use a command-line flag to figure out which version of the fuel //calculation to use let part_one = env.args.contains("--part-one", {(l, r) => l == r}) let part_two = env.args.contains("--part-two", {(l, r) => l == r}) if part_one or part_two then calculate_fuel(env, part_one) else env.err.print("Usage: 01 [--part-one|--part-two]") env.exitcode(99) end fun calculate_fuel(env: Env, part_one: Bool) => // since we're storing the input list externally, we'll need the //ability to read and also stat files, so build that capability let caps = recover val FileCaps.>set(FileRead).>set(FileStat) end try // try opening the file, whose name we've hard-coded with file = OpenFile(FilePath(env.root as AmbientAuth, "input.txt", caps)?) as File do // iterate through the lines of the file let sum = Iter[String](file.lines()) // try to parse all the lines as a number .filter_map[U64]({(str) => try str.u64()? else None end}) // calculate the amount of fuel required for each one .map[U64]({(x) => if part_one then Fuel.calc(x) else Fuel.calc_recursive(x) end }) // and sum them up .fold[U64](0, {(sum, x) => sum + x}) // print out the resulting number env.out.print(Format.int[U64](sum)) end else // if something failed, then print an error message of some kind and exit env.err.print("Couldn't read expected file `input.txt'") env.exitcode(99) end