Functional programming 具有递归函数的F#中的背包问题

Functional programming 具有递归函数的F#中的背包问题,functional-programming,f#,knapsack-problem,Functional Programming,F#,Knapsack Problem,我们必须用不同的编程类型为一个学校项目编程背包问题。一个是函数式编程,我正在用F#尝试它 我使用一个递归函数,总是将具有最高值的项目放入我的背包中。最后,我希望所有元素的总和都是最高的。这是Python中的解决方案,我只是希望能将其转移到F# let names=[“Zahnbürste”、“Zahn意面”、“出纳员”、“Duschgel”、“洗发水”、“Handtuch”、“Besteck”、“Trinkflasche”、“Becher”、“Taschenlampe”、“Sonnenshutz

我们必须用不同的编程类型为一个学校项目编程背包问题。一个是函数式编程,我正在用F#尝试它

我使用一个递归函数,总是将具有最高值的项目放入我的背包中。最后,我希望所有元素的总和都是最高的。这是Python中的解决方案,我只是希望能将其转移到F#

let names=[“Zahnbürste”、“Zahn意面”、“出纳员”、“Duschgel”、“洗发水”、“Handtuch”、“Besteck”、“Trinkflasche”、“Becher”、“Taschenlampe”、“Sonnenshutz”、“Medikamente”]
设体积=[2,4,5,2,2.5,10,5,3,3,9,2,1]
设值=[3,19,17,15,13,3,2,8,5,6,17,15]
maxVol=20;
def背包问题(restVol,i):
如果(i<(len(卷)):
dontPack=背包问题(restVol,i+1)
包装=0
如果(restVol-卷[i]>=0):
pack=值[i]+背包问题(restVol-卷[i],i+1)
如果(dontPack>pack):
返回dontPack
其他:
回程包
其他:
返回0
结果=背包问题(maxVol,0)
打印(结果)
这就是我在F#中尝试的。请帮我解决我的问题。我不熟悉F#,函数编程和其他解决背包问题的方法有数百行代码,似乎过于复杂了。这并没有真正打印我想从这个函数中得到的最终结果。它只返回0:


   open System

let names_list = ["Zahnbürste";"Zahnpasta"; "Teller"; "Duschgel";"Shampoo"; "Handtuch"; "Besteck"; "Trinkflasche"; "Becher";"Taschenlampe";"Sonnenschutz";"Medikamente"]
let volumes_list = [2;4;5;2;3;10;5;3;3;9;2;1]
let values_list = [3;19;17;15;13;3;2;8;5;6;17;15]
let maxVolume = 20
let rec rucksackProblem (restVol : int, i : int) =
    if i < volumes_list.Length then
       let dontPack = rucksackProblem(restVol, i + 1) 
       let pack = 0
       let currentVolumeItem = volumes_list.Item(i)
       if restVol - volumes_list.Item(i) >= 0 then
        let mutable pack = values_list.Item(i) + rucksackProblem(restVol - volumes_list.Item(i), i + 1)
        printf "%i" (volumes_list.Item(i))
        else()
       if dontPack > pack then
        dontPack
        else 
            pack

    else
        0

let result = rucksackProblem(maxVolume, 0)
printfn "%i" result


Console.ReadKey() |> ignore

开放系统
让姓名列表=[“Zahnbürste”;“Zahn意面”;“出纳员”;“杜施格尔”;“洗发水”;“手推车”;“Besteck”;“Trinkflasche”;“Becher”;“Taschenlampe”;“Sonnenschutz”;“Medikamente”]
让卷列表=[2;4;5;2;3;10;5;3;3;9;2;1]
让值_list=[3;19;17;15;13;3;2;8;5;6;17;15]
设maxVolume=20
let rec背包问题(restVol:int,i:int)=
如果我=0,则
let mutable pack=values\u list.Item(i)+rucksackProblem(restVol-volumes\u list.Item(i),i+1)
打印“%i”(卷列表项(i))
else()
如果不打包>打包,则
dontPack
其他的
打包
其他的
0
let结果=背包问题(最大容量,0)
printfn“%i”结果
Console.ReadKey()|>忽略

我无法保证算法的正确性或效率,但这应该满足您的要求:

 open System

let names_list = ["Zahnbürste";"Zahnpasta"; "Teller"; "Duschgel";"Shampoo"; "Handtuch"; "Besteck"; "Trinkflasche"; "Becher";"Taschenlampe";"Sonnenschutz";"Medikamente"]
let volumes_list = [2;4;5;2;3;10;5;3;3;9;2;1]
let values_list = [3;19;17;15;13;3;2;8;5;6;17;15]
let maxVolume = 20

let rec rucksackProblem (restVol : int)  (i : int) =
    if i < volumes_list.Length then
       let dontPack = rucksackProblem restVol (i + 1) 

       let currentVolumeItem = volumes_list.[i]

       let pack =  
            if restVol - volumes_list.[i] >= 0 then 
              values_list.[i] + rucksackProblem (restVol - volumes_list.[i])  (i + 1)
            else 0  

       if dontPack > pack then
            dontPack
       else 
            pack

    else
        0

let result = rucksackProblem maxVolume 0
printfn "%i" result
开放系统
让姓名列表=[“Zahnbürste”;“Zahn意面”;“出纳员”;“杜施格尔”;“洗发水”;“手推车”;“Besteck”;“Trinkflasche”;“Becher”;“Taschenlampe”;“Sonnenschutz”;“Medikamente”]
让卷列表=[2;4;5;2;3;10;5;3;3;9;2;1]
让值_list=[3;19;17;15;13;3;2;8;5;6;17;15]
设maxVolume=20
let rec背包问题(restVol:int)(i:int)=
如果我=0,则
值列表[i]+背包问题(restVol-卷列表[i])(i+1)
其他0
如果不打包>打包,则
dontPack
其他的
打包
其他的
0
让结果=背包问题最大卷0
printfn“%i”结果
请注意,因为可变包是在if范围内定义的,所以在if分支之外无法访问。我把这个定义移到上面,这样就可以在外面访问了


我还做了一些其他的改变。在F#中,列表中的项目可以作为list.[index]访问。参数以空格而不是逗号分隔传递,因为这是一种更灵活的方法,例如允许。

我不能保证算法的正确性或效率,但这应该满足您的要求:

 open System

let names_list = ["Zahnbürste";"Zahnpasta"; "Teller"; "Duschgel";"Shampoo"; "Handtuch"; "Besteck"; "Trinkflasche"; "Becher";"Taschenlampe";"Sonnenschutz";"Medikamente"]
let volumes_list = [2;4;5;2;3;10;5;3;3;9;2;1]
let values_list = [3;19;17;15;13;3;2;8;5;6;17;15]
let maxVolume = 20

let rec rucksackProblem (restVol : int)  (i : int) =
    if i < volumes_list.Length then
       let dontPack = rucksackProblem restVol (i + 1) 

       let currentVolumeItem = volumes_list.[i]

       let pack =  
            if restVol - volumes_list.[i] >= 0 then 
              values_list.[i] + rucksackProblem (restVol - volumes_list.[i])  (i + 1)
            else 0  

       if dontPack > pack then
            dontPack
       else 
            pack

    else
        0

let result = rucksackProblem maxVolume 0
printfn "%i" result
开放系统
让姓名列表=[“Zahnbürste”;“Zahn意面”;“出纳员”;“杜施格尔”;“洗发水”;“手推车”;“Besteck”;“Trinkflasche”;“Becher”;“Taschenlampe”;“Sonnenschutz”;“Medikamente”]
让卷列表=[2;4;5;2;3;10;5;3;3;9;2;1]
让值_list=[3;19;17;15;13;3;2;8;5;6;17;15]
设maxVolume=20
let rec背包问题(restVol:int)(i:int)=
如果我=0,则
值列表[i]+背包问题(restVol-卷列表[i])(i+1)
其他0
如果不打包>打包,则
dontPack
其他的
打包
其他的
0
让结果=背包问题最大卷0
printfn“%i”结果
请注意,因为可变包是在if范围内定义的,所以在if分支之外无法访问。我把这个定义移到上面,这样就可以在外面访问了


我还做了一些其他的改变。在F#中,列表中的项目可以作为list.[index]访问。参数传递时用空格而不是逗号分隔,因为这是一种更灵活的方法,例如允许。

我冒昧地重写了您的代码,结果就是这样


    let names = ["Zahnbürste"; "Zahnpasta"; "Teller"; "Duschgel"; "Shampoo"; "Handtuch"; "Besteck"; "Trinkflasche"; "Becher"; "Taschenlampe"; "Sonnenschutz"; "Medikamente"]
    let weights = [2; 4; 5; 2; 3; 10; 5; 3; 3; 9; 2; 1]
    let profits = [3; 19; 17; 15; 13; 3; 2; 8; 5; 6; 17; 15]
    let cap = 20

    type Product = { Name: string; Profit: int; Weight: int }

    let knappsack names profits weights cap =
        let sortItemsInDecreasingOrder =
            List.zip3 names profits weights
            |> List.map (fun x -> { Name=x.Item1; Profit=x.Item2; Weight=x.Item3 })
            |> List.sortBy (fun p -> p.Profit / p.Weight)
            |> List.rev
        let products = sortItemsInDecreasingOrder
        let rec pack bag totalWeight idx =
            if idx > List.length names - 1 then bag
            else
                let p = products.[idx]
                if (totalWeight + p.Weight) > cap then bag
                else
                    pack (bag @ [p]) (totalWeight + p.Weight) (idx + 1)
        pack List.empty 0 1

    knappsack names profits weights cap
    |> Dump
    |> ignore
我得到的结果是

Name Profit Weight Sonnenschutz 17 2 Duschgel 15 2 Shampoo 13 3 Zahnpasta 19 4 Teller 17 5 Trinkflasche 8 3 89 19 名称利润权重 松嫩舒茨17 2 杜施格尔15 2 洗发水13 3 扎恩19 4 出纳员17 5 Trinkflasche 8 3 89 19
顺便说一句,如果你对使用f#学习函数式编程感兴趣,我可以强烈推荐。

我冒昧地重写了你的代码,我最终得到了这个


    let names = ["Zahnbürste"; "Zahnpasta"; "Teller"; "Duschgel"; "Shampoo"; "Handtuch"; "Besteck"; "Trinkflasche"; "Becher"; "Taschenlampe"; "Sonnenschutz"; "Medikamente"]
    let weights = [2; 4; 5; 2; 3; 10; 5; 3; 3; 9; 2; 1]
    let profits = [3; 19; 17; 15; 13; 3; 2; 8; 5; 6; 17; 15]
    let cap = 20

    type Product = { Name: string; Profit: int; Weight: int }

    let knappsack names profits weights cap =
        let sortItemsInDecreasingOrder =
            List.zip3 names profits weights
            |> List.map (fun x -> { Name=x.Item1; Profit=x.Item2; Weight=x.Item3 })
            |> List.sortBy (fun p -> p.Profit / p.Weight)
            |> List.rev
        let products = sortItemsInDecreasingOrder
        let rec pack bag totalWeight idx =
            if idx > List.length names - 1 then bag
            else
                let p = products.[idx]
                if (totalWeight + p.Weight) > cap then bag
                else
                    pack (bag @ [p]) (totalWeight + p.Weight) (idx + 1)
        pack List.empty 0 1

    knappsack names profits weights cap
    |> Dump
    |> ignore
我得到的结果是

Name Profit Weight Sonnenschutz 17 2 Duschgel 15 2 Shampoo 13 3 Zahnpasta 19 4 Teller 17 5 Trinkflasche 8 3 89 19 名称利润权重 松嫩舒茨17 2 杜施格尔15 2 洗发水13 3 扎恩19 4 出纳员17 5 Trinkflasche 8 3 89 19 顺便说一句,如果你对使用f#学习函数式编程感兴趣,我可以