2023 パズル in F#
他の人の回答などを見ずに愚直に解いてみたが全部を算出しようとすると遅すぎた.
type Opcode = | Add | Sub | Mul | Div type Operand = | Opcode of Opcode | Number of int let calculateRpnExpression (exp: Operand list) : Option<int> = let rec calculateRpnExpression' exp stack = match exp with | [] -> Some(List.head stack) | Number (n) :: t -> calculateRpnExpression' t (n :: stack) | Opcode (op) :: t -> match stack with | n2 :: n1 :: rest -> match op with | Add -> calculateRpnExpression' t ((n1 + n2) :: rest) | Sub -> calculateRpnExpression' t ((n1 - n2) :: rest) | Mul -> calculateRpnExpression' t ((n1 * n2) :: rest) | Div -> if n2 = 0 then None else calculateRpnExpression' t ((n1 / n2) :: rest) | _ -> printfn $"stack=${stack} exp=${exp}" failwith "never reach here" calculateRpnExpression' exp [] let normalizeRpnExpression (exp: Operand list) : string = let rec normalizeRpnExpression' exp stack = match exp with | [] -> List.head stack | Number (n) :: t -> normalizeRpnExpression' t ((string n) :: stack) | Opcode (op) :: t -> match stack with | v2 :: v1 :: rest -> match op with | Add -> normalizeRpnExpression' t ((sprintf "(%s+%s)" v1 v2) :: rest) | Sub -> normalizeRpnExpression' t ((sprintf "(%s-%s)" v1 v2) :: rest) | Mul -> normalizeRpnExpression' t ((sprintf "(%s*%s)" v1 v2) :: rest) | Div -> normalizeRpnExpression' t ((sprintf "(%s/%s)" v1 v2) :: rest) | _ -> failwith "never reach here" normalizeRpnExpression' exp [] let createRpnExpression (nums: int list) (target: int) = let len = nums |> List.length let limit = len * 2 - 1 let rec createRpnExpression' nums prevNum numCount opCount exp acc = if numCount + opCount >= limit then let exp' = List.rev exp match calculateRpnExpression exp' with | None -> acc | Some (v) -> if v = target then printfn "%A" (normalizeRpnExpression exp') exp' :: acc else acc else let acc' = if numCount - opCount >= 2 then let ops = if prevNum = 8 then [ Div ] else [ Add; Sub; Mul; Div ] ops |> List.fold (fun acc' op -> createRpnExpression' nums -1 numCount (opCount + 1) (Opcode(op) :: exp) acc') acc else acc if prevNum <> 8 && numCount < len then let n = List.head nums createRpnExpression' (List.tail nums) n (numCount + 1) opCount (Number(n) :: exp) acc' else acc' createRpnExpression' nums -1 0 0 [] [] let quiz2023 (nums: int list) (target: int) : string list = let rpnExpressions = createRpnExpression nums target rpnExpressions |> List.map normalizeRpnExpression
この本に単純な場合のものは載っているので全くわからない人は見ても良いかもしれません。