June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -45,7 +45,6 @@ Show which items the thief carries in his knapsack so that their total weight do
*   [[Knapsack problem/0-1]]
<br><br>
;See also:
* &nbsp; Wikipedia article: &nbsp; [[wp:Continuous_knapsack_problem|continuous knapsack]].
<br><br>

View file

@ -1,29 +1,30 @@
immutable KPCSupply{S<:String, T<:Real}
item::S
struct KPCSupply{T<:Real}
item::String
weight::T
value::T
uvalue::T
end
Base.isless(a::KPCSupply, b::KPCSupply) = a.uvalue<b.uvalue
function KPCSupply{S<:String, T<:Real}(item::S, weight::T, value::T)
KPCSupply(item, weight, value, value/weight)
function KPCSupply(item::AbstractString, weight::Real, value::Real)
w, v = promote(weight, value)
KPCSupply(item, w, v, v / w)
end
function solve{S<:String, T<:Real}(store::Array{KPCSupply{S,T},1},
capacity::T)
ksack = KPCSupply{S,T}[]
Base.show(io::IO, s::KPCSupply) = print(io, s.item, @sprintf " (%.2f kg, %.2f €, %.2f €/kg)" s.weight s.value s.uvalue)
Base.isless(a::KPCSupply, b::KPCSupply) = a.uvalue < b.uvalue
function solve(store::Vector{KPCSupply{T}}, capacity::Real) where T<:Real
sack = similar(store, 0) # vector like store, but of length 0
kweight = zero(T)
for s in sort(store, rev=true)
if kweight + s.weight <= capacity
for s in sort(store, rev = true)
if kweight + s.weight capacity
kweight += s.weight
push!(ksack, s)
push!(sack, s)
else
w = capacity-kweight
v = w*s.uvalue
push!(ksack, KPCSupply(s.item, w, v, s.uvalue))
w = capacity - kweight
v = w * s.uvalue
push!(sack, KPCSupply(s.item, w, v, s.value))
break
end
end
return ksack
return sack
end

View file

@ -1,30 +1,14 @@
store = [KPCSupply("beef", 38//10, 36//1),
KPCSupply("pork", 54//10, 43//1),
KPCSupply("ham", 36//10, 90//1),
KPCSupply("greaves", 24//10, 45//1),
KPCSupply("flitch", 4//1, 30//1),
KPCSupply("brawn", 25//10, 56//1),
KPCSupply("welt", 37//10, 67//1),
KPCSupply("salami", 3//1, 95//1),
KPCSupply("sausage", 59//10, 98//1)]
store = [KPCSupply("beef", 38//10, 36),
KPCSupply("pork", 54//10, 43),
KPCSupply("ham", 36//10, 90),
KPCSupply("greaves", 24//10, 45),
KPCSupply("flitch", 4//1, 30),
KPCSupply("brawn", 25//10, 56),
KPCSupply("welt", 37//10, 67),
KPCSupply("salami", 3//1, 95),
KPCSupply("sausage", 59//10, 98)]
sack = solve(store, 15//1)
println("The store contains:")
println(" Item Weight Unit Price")
for s in store
println(@sprintf("%12s %4.1f %6.2f",
s.item, float(s.weight), float(s.uvalue)))
end
println()
println("The thief should take:")
println(" Item Weight Value")
for s in sack
println(@sprintf("%12s %4.1f %6.2f",
s.item, float(s.weight), float(s.value)))
end
w = mapreduce(x->x.weight, +, sack)
v = mapreduce(x->x.value, +, sack)
println(@sprintf("%12s %4.1f %6.2f",
"Total", float(w), float(v)))
sack = solve(store, 15)
println("The store contains:\n - ", join(store, "\n - "))
println("\nThe thief should take::\n - ", join(sack, "\n - "))
@printf("\nTotal value in the sack: %.2f €\n", sum(getfield.(sack, :value)))

View file

@ -0,0 +1,57 @@
import scala.annotation.tailrec
object ContinousKnapsackForRobber extends App {
val MaxWeight = 15.0
val items = Seq(
Item("Beef", 3.8, 3600),
Item("Pork", 5.4, 4300),
Item("Ham", 3.6, 9000),
Item("Greaves", 2.4, 4500),
Item("Flitch", 4.0, 3000),
Item("Brawn", 2.5, 5600),
Item("Welt", 3.7, 6700),
Item("Salami", 3.0, 9500),
Item("Sausage", 5.9, 9800))
// sort items by value per unit weight in descending order
def sortedItems = items.sortBy(it => -it.value / it.weight)
@tailrec
def packer(notPacked: Seq[Item], packed: Lootsack): Lootsack = {
if (!packed.isNotFull || notPacked.isEmpty) packed
else {
val try2fit = packed.copy(bagged = notPacked.head +: packed.bagged)
if (try2fit.isNotFull) packer(notPacked.tail, try2fit)
else {
try2fit.copy(lastPiece = packed.weightLeft / notPacked.head.weight)
}
}
}
case class Item(name: String, weight: Double, value: Int)
case class Lootsack(bagged: Seq[Item], lastPiece: Double = 1.0) {
private val totWeight = if (bagged.isEmpty) 0.0
else bagged.tail.map(_.weight).sum + bagged.head.weight * lastPiece
def isNotFull: Boolean = weightLeft > 0
def weightLeft: Double = MaxWeight - totWeight
override def toString = f"${show(bagged, lastPiece)}Totals: weight: $totWeight%4.1f, value: $totValue%6.2f"
private def totValue: BigDecimal = if (bagged.isEmpty) 0.0
else (bagged.tail.map(_.value).sum + bagged.head.value * lastPiece) / 100
private def show(is: Seq[Item], percentage: Double) = {
def toStr(is: Seq[Item], percentage: Double = 1): String =
is.map(it => f"${percentage * 100}%6.2f%% ${it.name}%-7s ${
it.weight * percentage}%4.1f ${it.value * percentage / 100}%6.2f\n").mkString
toStr(is.tail.reverse) + toStr(Seq(is.head), percentage)
}
}
println(packer(sortedItems, Lootsack(Nil)))
}