Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Security.Policy
Imports System.Text
Imports System.Threading.Tasks
Namespace CuttingStock
Class Program
'The possible lengths of plank
Private Shared PossibleLengths As New List(Of Single) From {6000}
Private Shared Sub Main(args As String())
'The cuts to be made
Dim DesiredLengths As New List(Of Single) From {1700, 1450, 2050, 1950, 1950, 1950, 1000, 1802, 1400, 326, 1204, 3100, 802, 1407}
'Perform some basic optimisations
DesiredLengths.Sort()
DesiredLengths.Reverse()
'Cut!
Dim planks = CalculateCuts(DesiredLengths)
Console.WriteLine()
For Each plank In planks
Console.WriteLine("Cut a {0} long plank by: {1} to end up with {2} waste.", plank.OriginalLength, String.Join(", ", plank.Cuts), plank.FreeLength)
Next
Console.WriteLine("Finished with {0} waste", GetFree(planks))
Console.ReadKey()
End Sub
'Calculate how much waste/free length is left in a list of planks
Private Shared Function GetFree(planks As List(Of Plank)) As Single
Dim free As Single = 0
For Each plank In planks
free += plank.FreeLength
Next
Return free
End Function
Private Shared Function CalculateCuts(desired As List(Of Single)) As List(Of Plank)
Dim planks = New List(Of Plank)() 'Buffer list
'go through cuts
For Each i In desired
'if no eligible planks can be found
If Not planks.Any(Function(plank) plank.FreeLength >= i) Then
'make a plank
planks.Add(New Plank(PossibleLengths.Max()))
End If
'cut where possible
For Each plank In planks.Where(Function(plank) plank.FreeLength >= i)
plank.Cut(i)
Exit For
Next
Next
'cut down on waste by minimising length of plank
For Each plank In planks
Dim newLength As Single = plank.OriginalLength
For Each possibleLength In PossibleLengths
If possibleLength <> plank.OriginalLength AndAlso plank.OriginalLength - plank.FreeLength <= possibleLength Then
newLength = possibleLength
Exit For
End If
Next
plank.OriginalLength = newLength
Next
Return planks
End Function
End Class
'class for a generic 'plank'
Class Plank
Public Sub New(length As Single)
OriginalLength = length
End Sub
Public ReadOnly Property FreeLength() As Single
Get
Return OriginalLength - Cuts.Sum()
End Get
End Property
Public OriginalLength As Single
Public Cuts As New List(Of Single)()
Public Sub Cut(cutLength As Single)
Cuts.Add(cutLength)
End Sub
End Class
End Namespace