Repository navigation
Expand file tree
/
Copy pathrecursion2.py
More file actions
283 lines (240 loc) · 13.1 KB
/
Copy pathrecursion2.py
File metadata and controls
283 lines (240 loc) · 13.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File: recursion2.py
# Description:Second Recursion tests
# Student Name:Daniel Espinoza
# Student UT EID:dee467
# Partner's Name:Mark Simmons
# Partner's UT EID:mjs5839
# Course Name: CS 313E
# Unique Number:51350
# Date Created: 10/12/2018
# Date Last Modified: 10/15/2018
# Given an array of ints, is it possible to choose a group of some
# of the ints, such that the group sums to the given target?
# This is a classic backtracking recursion problem. Once you
# understand the recursive backtracking strategy in this problem,
# you can use the same pattern for many problems to search a space
# of choices. Rather than looking at the whole array, our convention
# is to consider the part of the array starting at index start and
# continuing to the end of the array. The caller can specify the
# whole array simply by passing start as 0. No loops are needed --
# the recursive calls progress down the array.
def groupSum(start, nums, target):
if target == 0:
return True
elif start >= len(nums):
return False
elif nums[start] == target:
return True
else:
return groupSum(start+1, nums, target-nums[start]) or \
groupSum(start+1, nums, target)
# Given an array of ints, is it possible to choose a group of some
# of the ints, beginning at the start index, such that the group
# sums to the given target? However, with the additional constraint
# that all 6's must be chosen. (No loops needed.)
def groupSum6(start, nums, target):
if start >= len(nums):
return target == 0
elif nums[start] == 6:
return groupSum6(start+1, nums, target-nums[start])
else:
return groupSum6(start+1, nums, target-nums[start]) or \
groupSum6(start+1, nums, target)
# Given an array of ints, is it possible to choose a group of some
# of the ints, such that the group sums to the given target with this
# additional constraint: If a value in the array is chosen to be in
# the group, the value immediately following it in the array must
# not be chosen. (No loops needed.)
def groupNoAdj(start, nums, target):
# base case; if Target is zero then the case is final
if target==0:
return True;
# the start cannot be larger
elif (start>= len(nums)):
return False
# so it goes throught this and skips over the adjacent value
elif(groupNoAdj(start+2,nums,target-nums[start])):
return True
else:
# this goes to the next intial element
return groupNoAdj(start+1,nums,target)
# Given an array of ints, is it possible to choose a group
# of some of the ints, such that the group sums to the given
# target with these additional constraints: all multiples of
# 5 in the array must be included in the group. If the value
# immediately following a multiple of 5 is 1, it must not
# be chosen. (No loops needed.)
def groupSum5(start, nums, target):
if start >= len(nums):
return target == 0
elif nums[start] % 5 == 0:
if start < len(nums)-1 and nums[start+1] == 1:
return groupSum5(start+2, nums, target-nums[start])
else:
return groupSum5(start+1, nums, target-nums[start])
else:
return groupSum5(start+1, nums, target-nums[start]) or \
groupSum5(start+1, nums, target)
# Given an array of ints, is it possible to choose a
# group of some of the ints, such that the group sums
# to the given target, with this additional constraint:
# if there are numbers in the array that are adjacent
# and the identical value, they must either all be chosen,
# or none of them chosen. For example, with the array
# [1, 2, 2, 2, 5, 2], either all three 2's in the middle
# must be chosen or not, all as a group. (one loop can
# be used to find the extent of the identical values).
def groupSumClump(start, nums, target):
if start>=len(nums):
return target==0
else:
# so we start with the adjacent value
clump=start+1
# if the clump is good we should use it if not completely skip all
# them by going the distance of the clump + start
for x in range(clump,len(nums)):
if nums[start] ==nums[x]:
clump+=1
if (groupSumClump(clump, nums, target - ((clump - start) * nums[start]))):
return True
# Theres no point of staying in the clump area if it doesn't work
return groupSumClump(clump,nums,target)
# Given an array of ints, is it possible to divide the
# ints into two groups, so that the sums of the two
# groups are the same. Every int must be in one group
# or the other. Write a recursive helper method that
# takes whatever arguments you like, and make the
# initial call to your recursive helper from splitArray().
# (No loops needed.)
def splitArray(nums):
return splitArrayHelper(nums, 0, [], [])
def splitArrayHelper(nums, start, a, b):
#print(a, b) #-debugging
if start == len(nums):
return sum(a) == sum(b)
else:
a2 = a[:]
a2.append(nums[start])
b2 = b[:]
b2.append(nums[start])
return splitArrayHelper(nums, start+1, a2, b) or \
splitArrayHelper(nums, start+1, a, b2)
# Given an array of ints, is it possible to divide the
# ints into two groups, so that the sum of one group
# is a multiple of 10, and the sum of the other group
# is odd. Every int must be in one group or the other.
# Write a recursive helper method that takes whatever
# arguments you like, and make the initial call to your
# recursive helper from splitOdd10(). (No loops needed.)
## SIMILAR TO sub_sets
def splitOdd10(nums):
return splitOdd10Helper(nums,0,[],[])
def splitOdd10Helper(nums,start,a,b):
if start == len(nums):
# if we get to the end the we append
# last element to create the b array
b_sum=sum(b)
b.append(b_sum)
else:
# will equal all the elements in a
c = a[:]
#append the element
a.append(nums[start])
splitOdd10Helper(nums,start+1,a,b)
splitOdd10Helper(nums,start+1,c,b)
#make sure the parted groups meet the conditions
return (sum(a)%10==0 and sum(b)%2==1) or \
(sum(b)%10==0 and sum(a)%2==1)
# Given an array of ints, is it possible to divide the ints
# into two groups, so that the sum of the two groups is the
# same, with these constraints: all the values that are
# multiple of 5 must be in one group, and all the values
# that are a multiple of 3 (and not a multiple of 5)
# must be in the other. (No loops needed.)
def split53(nums):
return split53Helper(nums, 0, [], [])
def split53Helper(nums, start, a, b):
if start == len(nums):
return sum(a) == sum(b)
elif nums[start] % 5 == 0:
a.append(nums[start])
return split53Helper(nums, start+1, a, b)
elif nums[start] % 3 == 0:
b.append(nums[start])
return split53Helper(nums, start+1, a, b)
else:
a2 = a[:]
a2.append(nums[start])
b2 = b[:]
b2.append(nums[start])
return split53Helper(nums, start+1, a2, b) or \
split53Helper(nums, start+1, a, b2)
#######################################################################################################
#######################################################################################################
# #
# DO NOT MODIFY ANYTHING BELOW THIS LINE !! #
# #
#######################################################################################################
#######################################################################################################
def main(argv):
problems = ["groupSum", "groupSum6", "groupNoAdj", "groupSum5", "groupSumClump", "splitArray", "splitOdd10", "split53"]
if len(argv) == 0:
printHelp()
exit(1)
elif "all" in argv:
argv = problems
for problem in argv:
if not problem in problems:
printHelp()
exit(1)
groupSum_args = [(0, [2, 4, 8], 10), (0, [2, 4, 8], 14), (0, [2, 4, 8], 9), (0, [2, 4, 8], 8), (1, [2, 4, 8], 8), (1, [2, 4, 8], 2), (0, [1], 1), (0, [9], 1), (1, [9], 0), (0, [], 0), (0, [10, 2, 2, 5], 17), (0, [10, 2, 2, 5], 15), (0, [10, 2, 2, 5], 9)]
groupSum6_args = [(0, [5, 6, 2], 8), (0, [5, 6, 2], 9), (0, [5, 6, 2], 7), (0, [1], 1), (0, [9], 1), (0, [], 0), (0, [3, 2, 4, 6], 8), (0, [6, 2, 4, 3], 8), (0, [5, 2, 4, 6], 9), (0, [6, 2, 4, 5], 9), (0, [3, 2, 4, 6], 3), (0, [1, 6, 2, 6, 4], 12), (0, [1, 6, 2, 6, 4], 13), (0, [1, 6, 2, 6, 4], 4), (0, [1, 6, 2, 6, 4], 9), (0, [1, 6, 2, 6, 5], 14), (0, [1, 6, 2, 6, 5], 15), (0, [1, 6, 2, 6, 5], 16)]
groupNoAdj_args = [(0, [2, 5, 10, 4], 12), (0, [2, 5, 10, 4], 14), (0, [2, 5, 10, 4], 7), (0, [2, 5, 10, 4, 2], 7), (0, [2, 5, 10, 4], 9), (0, [10, 2, 2, 3, 3], 15), (0, [10, 2, 2, 3, 3], 7), (0, [], 0), (0, [1], 1), (0, [9], 1), (0, [9], 0), (0, [5, 10, 4, 1], 11)]
groupSum5_args = [(0, [2, 5, 10, 4], 19), (0, [2, 5, 10, 4], 17), (0, [2, 5, 10, 4], 12), (0, [2, 5, 4, 10], 12), (0, [3, 5, 1], 4), (0, [3, 5, 1], 5), (0, [1, 3, 5], 5), (0, [3, 5, 1], 9), (0, [2, 5, 10, 4], 7), (0, [2, 5, 10, 4], 15), (0, [2, 5, 10, 4], 11), (0, [1], 1), (0, [9], 1), (0, [9], 0), (0, [], 0)]
groupSumClump_args = [(0, [2, 4, 8], 10), (0, [1, 2, 4, 8, 1], 14), (0, [2, 4, 4, 8], 14), (0, [8, 2, 2, 1], 9), (0, [8, 2, 2, 1], 11), (0, [1], 1), (0, [9], 1)]
splitArray_args = [([2, 2]), ([2, 3]), ([5, 2, 3]), ([5, 2, 2]), ([1, 1, 1, 1, 1, 1]), ([1, 1, 1, 1, 1]), ([]), ([1]), ([3, 5]), ([5, 3, 2]), ([2,2,10,10,1,1]), ([1,2,2,10,10,1,1]), ([1,2,3,10,10,1,1])]
splitOdd10_args = [[5, 5, 5], [5, 5, 6], [5, 5, 6, 1], [6, 5, 5, 1], [6, 5, 5, 1, 10], [6, 5, 5, 5, 1], [1], [], [10, 7, 5, 5], [10, 0, 5, 5], [10, 7, 5, 5, 2], [10, 7, 5, 5, 1]]
split53_args = [[1,1], [1, 1, 1], [2, 4, 2], [2, 2, 2, 1], [3, 3, 5, 1], [3, 5, 8], [2, 4, 6], [3, 5, 6, 10, 3, 3]]
groupSum_ans = [True, True, False, True, True, False, True, False, True, True, True, True, True]
groupSum6_ans = [True, False, False, True, False, True, True, True, False, False, False, True, True, False, False, True, True, False]
groupNoAdj_ans = [True, False, False, True, True, True, False, True, True, False, True, True]
groupSum5_ans = [True, True, False, False, False, True, True, False, False, True, False, True, False, True, True]
groupSumClump_ans = [True, True, False, True, False, True, False]
splitArray_ans = [True, False, True, False, True, False, True, False, False, True, True, False, True]
splitOdd10_ans = [True, False, True, True, True, False, True, False, True, False, True, False]
split53_ans = [True, False, True, False, True, False, True, True]
for prob in argv:
correct = 0 # counts number of test cases passed
leftParen = "("
rightParen = ")"
# loop over test cases
for i in range(len(locals()[prob+"_args"])):
if type(locals()[prob+"_args"][i]) is tuple:
leftParen = rightParen = ""
if (type(locals()[prob+"_args"][i]) is str) or (type(locals()[prob+"_args"][i]) is int) or (type(locals()[prob+"_args"][i]) is list) or (len(locals()[prob+"_args"][i]) == 1): # function takes one argument
if globals()[prob](locals()[prob+"_args"][i]) == locals()[prob+"_ans"][i]:
print ("\nCorrect!", prob + leftParen + str(locals()[prob+"_args"][i]) + rightParen + " result:", str(globals()[prob](locals()[prob+"_args"][i])), " expected:", str(locals()[prob+"_ans"][i]))
correct += 1
else: # print fail message
print ("\nWrong!", prob + leftParen + str(locals()[prob+"_args"][i]) + rightParen + " result:", str(globals()[prob](locals()[prob+"_args"][i])), " expected:", str(locals()[prob+"_ans"][i]))
elif len(locals()[prob+"_args"][i]) == 2: # there are two arguments to function
first, second = locals()[prob+"_args"][i]
if globals()[prob](first, second) == locals()[prob+"_ans"][i]:
print ("\nCorrect!", prob + leftParen + str(locals()[prob+"_args"][i]) + rightParen + " result:", str(globals()[prob](first, second)), " expected:", str(locals()[prob+"_ans"][i]))
correct += 1
else: # print fail message
print ("\nWorng!", prob + leftParen + str(locals()[prob+"_args"][i]) + rightParen + " result:", str(globals()[prob](first, second)), " expected:", str(locals()[prob+"_ans"][i]))
else:
first, second, third = locals()[prob+"_args"][i]
if globals()[prob](first, second, third) == locals()[prob+"_ans"][i]:
print ("\nCorrect!", prob + leftParen + str(locals()[prob+"_args"][i]) + rightParen + " result:", str(globals()[prob](first, second, third)), " expected:", str(locals()[prob+"_ans"][i]))
correct += 1
else: # print fail message
print ("\nWrong!", prob + leftParen + str(locals()[prob+"_args"][i]) + rightParen + " result:", str(globals()[prob](first, second, third)), " expected:", str(locals()[prob+"_ans"][i]))
print ("\n" + prob + ": passed", correct, "out of", len(locals()[prob+"_ans"]), "\n")
def printHelp():
print ("\nInvoke this script with the name of the function you wish to test.")
print ("e.g. python recursion1.py factorial")
print ("Invoke with \"python recursion1.py all\" to run all of the function tests\n")
import sys
main(sys.argv[1:])