code_junkie

Adding values in various combinations

Nov 13th, 2011
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.28 KB | None | 0 0
  1. def setNumbers(n): return 2**n-1
  2.  
  3. print(setNumbers(15))
  4.  
  5. def combs(arr):
  6. r = set()
  7.  
  8. for i in range(len(arr)):
  9. v = arr[i]
  10. new = set()
  11.  
  12. new.add(v)
  13. for a in r: new.add(a+v)
  14. r |= new
  15.  
  16. return r
  17.  
  18.  
  19. def subsetSum(arr, val):
  20. middle = len(arr)//2
  21.  
  22. seta = combs(arr[:middle])
  23. setb = combs(arr[middle:])
  24.  
  25. for a in seta:
  26. if (val-a) in setb:
  27. return True
  28.  
  29. return False
  30.  
  31. print(subsetSum([2, 3, 5, 8, 9], 8))
  32.  
  33. 001 = A
  34. 010 = B
  35. 011 = A+B
  36. 100 = C
  37. 101 = A+C
  38. 110 = B+C
  39. 111 = A+B+C
  40.  
  41. Option Explicit On
  42.  
  43. Public Class SubsetSum
  44. 'Class to solve exact integer Subset Sum problems'
  45. ''
  46. ' 06-sep-09 RBarryYoung Created.'
  47. Dim Power2() As Integer = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32764}
  48. Public ForceMatch As Boolean
  49. Public watch As New Stopwatch
  50. Public w0 As Integer, w1 As Integer, w1a As Integer, w2 As Integer, w3 As Integer, w4 As Integer
  51.  
  52.  
  53. Public Function SolveMany(ByVal ItemCount As Integer, ByVal Range As Integer, ByVal Iterations As Integer) As Integer
  54. ' Solve many subset sum problems in sequence.'
  55. ''
  56. ' 06-sep-09 RBarryYoung Created.'
  57. Dim TotalFound As Integer
  58. Dim Items() As Integer
  59. ReDim Items(ItemCount - 1)
  60.  
  61. 'First create our list of selectable items:'
  62. Randomize()
  63. For item As Integer = 0 To Items.GetUpperBound(0)
  64. Items(item) = Rnd() * Range
  65. Next
  66.  
  67. For iteration As Integer = 1 To Iterations
  68. Dim TargetSum As Integer
  69. If ForceMatch Then
  70. 'Use a random value but make sure that it can be matched:'
  71.  
  72. ' First, make a random bitmask to use:'
  73. Dim bits As Integer = Rnd() * (2 ^ (Items.GetUpperBound(0) + 1) - 1)
  74.  
  75. ' Now enumerate the bits and match them to the Items:'
  76. Dim sum As Integer = 0
  77. For b As Integer = 0 To Items.GetUpperBound(0)
  78. 'build the sum from the corresponding items:'
  79. If b < 16 Then
  80. If Power2(b) = (bits And Power2(b)) Then
  81. sum = sum + Items(b)
  82. End If
  83. Else
  84. If Power2(b - 15) * Power2(15) = (bits And (Power2(b - 15) * Power2(15))) Then
  85. sum = sum + Items(b)
  86. End If
  87. End If
  88. Next
  89. TargetSum = sum
  90.  
  91. Else
  92. 'Use a completely random Target Sum (low chance of matching): (Range / 2^ItemCount)'
  93. TargetSum = ((Rnd() * Range / 4) + Range * (3.0 / 8.0)) * ItemCount
  94. End If
  95.  
  96. 'Now see if there is a match'
  97. If SolveOne(TargetSum, ItemCount, Range, Items) Then TotalFound += 1
  98. Next
  99.  
  100. Return TotalFound
  101. End Function
  102.  
  103. Public Function SolveOne(ByVal TargetSum As Integer, ByVal ItemCount As Integer _
  104. , ByVal Range As Integer, ByRef Items() As Integer) As Boolean
  105. ' Solve a single Subset Sum problem: determine if the TargetSum can be made from'
  106. 'the integer items.'
  107.  
  108. 'first split the items into two half-lists: [O(n)]'
  109. Dim H1() As Integer, H2() As Integer
  110. Dim hu1 As Integer, hu2 As Integer
  111. If ItemCount Mod 2 = 0 Then
  112. 'even is easy:'
  113. hu1 = (ItemCount / 2) - 1 : hu2 = (ItemCount / 2) - 1
  114. ReDim H1((ItemCount / 2) - 1), H2((ItemCount / 2) - 1)
  115. Else
  116. 'odd is a little harder, give the first half the extra item:'
  117. hu1 = ((ItemCount + 1) / 2) - 1 : hu2 = ((ItemCount - 1) / 2) - 1
  118. ReDim H1(hu1), H2(hu2)
  119. End If
  120.  
  121. For i As Integer = 0 To ItemCount - 1 Step 2
  122. H1(i / 2) = Items(i)
  123. 'make sure that H2 doesnt run over on the last item of an odd-numbered list:'
  124. If (i + 1) <= ItemCount - 1 Then
  125. H2(i / 2) = Items(i + 1)
  126. End If
  127. Next
  128.  
  129. 'Now generate all of the sums for each half-list: [O( 2^(n/2) * n )] **(this is the slowest step)'
  130. Dim S1() As Integer, S2() As Integer
  131. Dim sum1 As Integer, sum2 As Integer
  132. Dim su1 As Integer = 2 ^ (hu1 + 1) - 1, su2 As Integer = 2 ^ (hu2 + 1) - 1
  133. ReDim S1(su1), S2(su2)
  134.  
  135. For i As Integer = 0 To su1
  136. ' Use the binary bitmask of our enumerator(i) to select items to use in our candidate sums:'
  137. sum1 = 0 : sum2 = 0
  138. For b As Integer = 0 To hu1
  139. If 0 < (i And Power2(b)) Then
  140. sum1 += H1(b)
  141. If i <= su2 Then sum2 += H2(b)
  142. End If
  143. Next
  144. S1(i) = sum1
  145. If i <= su2 Then S2(i) = sum2
  146. Next
  147.  
  148. 'Sort both lists: [O( 2^(n/2) * n )] **(this is the 2nd slowest step)'
  149. Array.Sort(S1)
  150. Array.Sort(S2)
  151.  
  152. ' Start the first half-sums from lowest to highest,'
  153. 'and the second half sums from highest to lowest.'
  154. Dim i1 As Integer = 0, i2 As Integer = su2
  155.  
  156. ' Now do a merge-match on the lists (but reversing S2) and looking to '
  157. 'match their sum to the target sum: [O( 2^(n/2) )]'
  158. Dim sum As Integer
  159. Do While i1 <= su1 And i2 >= 0
  160. sum = S1(i1) + S2(i2)
  161. If sum < TargetSum Then
  162. 'if the Sum is too low, then we need to increase the ascending side (S1):'
  163. i1 += 1
  164. ElseIf sum > TargetSum Then
  165. 'if the Sum is too high, then we need to decrease the descending side (S2):'
  166. i2 -= 1
  167. Else
  168. 'Sums match:'
  169. Return True
  170. End If
  171. Loop
  172.  
  173. 'if we got here, then there are no matches to the TargetSum'
  174. Return False
  175. End Function
  176.  
  177. End Class
  178.  
  179. Public Class frmSubsetSum
  180.  
  181. Dim ssm As New SubsetSum
  182.  
  183. Private Sub btnGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGo.Click
  184. Dim Total As Integer
  185. Dim datStart As Date, datEnd As Date
  186. Dim Iterations As Integer, Range As Integer, NumberCount As Integer
  187.  
  188. Iterations = CInt(txtIterations.Text)
  189. Range = CInt(txtRange.Text)
  190. NumberCount = CInt(txtNumberCount.Text)
  191.  
  192. ssm.ForceMatch = chkForceMatch.Checked
  193.  
  194. datStart = Now
  195.  
  196. Total = ssm.SolveMany(NumberCount, Range, Iterations)
  197.  
  198. datEnd = Now()
  199.  
  200. lblStart.Text = datStart.TimeOfDay.ToString
  201. lblEnd.Text = datEnd.TimeOfDay.ToString
  202. lblRate.Text = Format(Iterations / (datEnd - datStart).TotalMilliseconds * 1000, "####0.0")
  203.  
  204. ListBox1.Items.Insert(0, "Found " & Total.ToString & " Matches out of " & Iterations.ToString & " tries.")
  205. ListBox1.Items.Insert(1, "Tics 0:" & ssm.w0 _
  206. & " 1:" & Format(ssm.w1 - ssm.w0, "###,###,##0") _
  207. & " 1a:" & Format(ssm.w1a - ssm.w1, "###,###,##0") _
  208. & " 2:" & Format(ssm.w2 - ssm.w1a, "###,###,##0") _
  209. & " 3:" & Format(ssm.w3 - ssm.w2, "###,###,##0") _
  210. & " 4:" & Format(ssm.w4 - ssm.w3, "###,###,##0") _
  211. & ", tics/sec = " & Stopwatch.Frequency)
  212. End Sub
  213. End Class
Add Comment
Please, Sign In to add comment