我遇到一个问题,当我向其附加另一个切割时,“ all_possible_cuts”数组发生了变化。
我的代码中与该问题有关的特定部分是:
def append_to_all_possible_cuts(next_cuts):
"""Appends the next possible way to cut the material to the array \"all_possible_cuts\" """
Order.all_possible_cuts.append(next_cuts[:])
previous_cuts = next_cuts
return(previous_cuts)
...
Print(Order.all_possible_cuts)
输出:[[[19.125, 0], [16.125, 0]], [[19.125, 0], [16.125, 0]], ...[[19.125, 0], [16.125, 0]]]
预期输出:[[19.125, 6], [16.125, 1]], [[19.125, 6], [16.125, 0]], [[19.125, 5], [16.125, 3]],...[[19.125, 0], [16.125, 0]]
我发现有人遇到同样问题的文章,但我尝试了他们的解决方案,但似乎无济于事。
输入输入144、2、19、15、16、30
这是我的完整代码:
class Order:
purchase_lines = []
all_possible_cuts = []
def get_order_information():
"""Gathers all the starting bar length and cutting information from the order and sorts from largest cut to smallest cut."""
Order.get_starting_material_length()
Order.get_purchase_lines()
Order.purchase_lines = sorted(Order.purchase_lines, reverse=True)
def get_starting_material_length():
"""Gathers the length of the stock bar for the order. Returns starting lenght of the stock material."""
starting_material_length = int(input("What is the length of the stock (in inches)? "))
Order.starting_material_length = starting_material_length
def get_purchase_lines():
"""Gathers all the cut lengths and the quantities needed for each cut length. Adds a tolerance of 0.125 inches to each cutting length. Appends length + quantity needed to """
tolerance = 0.125
num_of_cut_lengths = int(input("How many different cut lengths are there? "))
for cut_length in range(num_of_cut_lengths):
length = float(input("What is the length of the cut (in inches)? "))
qty = int(input("How many " + str(length) + " in. cuts are needed? "))
Order.purchase_lines.append([(length + tolerance), qty])
def generate_all_possible_cuts():
"""Generates an array of every possible way to cut a single piece of stock material"""
first_possible_cut = Order.generate_first_possible_cut(Order.purchase_lines)
another_cut_possible = Order.determine_if_another_cut_possible(first_possible_cut)
previous_cuts = first_possible_cut
while another_cut_possible:
next_cuts = Order.generate_next_possible_cut(previous_cuts)
previous_cuts = Order.append_to_all_possible_cuts(next_cuts)
another_cut_possible = Order.determine_if_another_cut_possible(previous_cuts)
def generate_first_possible_cut(purchase_lines):
"""Using the cut lengths and quantities need, cutting the most pieces possible out of the stock material, starting with the first cut length entered, until the material has remainder of 0 or all cutting lengths have been attempted."""
possible_cut_length_and_qtys = []
remaining_material_length = Order.starting_material_length
for line in purchase_lines:
possible_cut_length = line[0]
max_qty = line[1]
possible_qty = int(remaining_material_length // possible_cut_length)
if possible_qty >= 0 and remaining_material_length - (possible_cut_length * possible_qty) >= 0:
if possible_qty > max_qty:
possible_cut_length_and_qtys.append([possible_cut_length, max_qty])
remaining_material_length -= possible_cut_length * max_qty
else:
possible_cut_length_and_qtys.append([possible_cut_length, possible_qty])
remaining_material_length -= possible_cut_length * possible_qty
Order.remaining_material_length = remaining_material_length
return(possible_cut_length_and_qtys)
def determine_if_another_cut_possible(previous_cuts):
"""Determines if another cut is possible. Returns True if possible, False if not possible."""
for cut in previous_cuts:
cut_qty = cut[1]
if cut_qty > 0:
return(True)
break
else:
return(False)
def generate_next_possible_cut(previous_cuts):
"""Using the previous counts, generates the next possible cut."""
index_of_lowered_digit, lowered_cuts = Order.lower_smallest_digit_possible(previous_cuts)
Order.increase_remaining_material_length(index_of_lowered_digit)
next_cuts = Order.use_remaining_stock(index_of_lowered_digit, lowered_cuts)
return(next_cuts)
def append_to_all_possible_cuts(next_cuts):
"""Appends the next possible way to cut the material to the array \"all_possible_cuts\" """
Order.all_possible_cuts.append(next_cuts[:])
previous_cuts = next_cuts
return(previous_cuts)
def lower_smallest_digit_possible(previous_cuts):
"""Using the previous counts, generates the next possible cut."""
current_cut_index = len(previous_cuts) - 1
while current_cut_index >= 0:
if previous_cuts[current_cut_index][1] > 0:
previous_cuts[current_cut_index][1] -= 1
break
else:
current_cut_index -= 1
return(current_cut_index, previous_cuts)
def increase_remaining_material_length(index_of_lowered_digit):
"""Using the previous counts, generates the next possible cut."""
Order.remaining_material_length += Order.purchase_lines[index_of_lowered_digit][0]
def use_remaining_stock(index_of_lowered_digit, lowered_cuts):
"""Using the previous counts, generates the next possible cut."""
current_index = index_of_lowered_digit + 1
while current_index < len(lowered_cuts):
if Order.remaining_material_length >= lowered_cuts[current_index][0]:
qty = int(Order.remaining_material_length // lowered_cuts[current_index][0])
lowered_cuts[current_index][1] += qty
Order.remaining_material_length -= lowered_cuts[current_index][0] * qty
current_index += 1
return(lowered_cuts)
Order.get_order_information()
Order.generate_all_possible_cuts()
答案 0 :(得分:0)
当您打算复制数组时,看起来您正在重用数组(又称Python列表)。
为了快速证明这一点,我将代码中返回数组的每个return语句更改为返回copy.deepcopy(a)
,其中a
是数组的名称。更改后的代码将产生预期的输出。
完整的更改代码包含在此答案的底部。
为帮助一般地解释问题,请考虑以下示例代码:
a = [0, 1, 2, 3, 4]
b = [a, a, a, a]
print(b)
a[0] = 123
print(b)
示例代码的输出为:
[[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]
[[123, 1, 2, 3, 4], [123, 1, 2, 3, 4], [123, 1, 2, 3, 4], [123, 1, 2, 3, 4]]
原因是因为a
数组从未复制到b
中。 b
数组仅获得 name a
的4个副本,而不是整个名为a
的数组。更正式地讲,这意味着a
被“按引用”使用。
完整更改的代码:
import copy
class Order:
purchase_lines = []
all_possible_cuts = []
def get_order_information():
"""Gathers all the starting bar length and cutting information from the order and sorts from largest cut to smallest cut."""
Order.get_starting_material_length()
Order.get_purchase_lines()
Order.purchase_lines = sorted(Order.purchase_lines, reverse=True)
def get_starting_material_length():
"""Gathers the length of the stock bar for the order. Returns starting lenght of the stock material."""
starting_material_length = int(input("What is the length of the stock (in inches)? "))
Order.starting_material_length = starting_material_length
def get_purchase_lines():
"""Gathers all the cut lengths and the quantities needed for each cut length. Adds a tolerance of 0.125 inches to each cutting length. Appends length + quantity needed to """
tolerance = 0.125
num_of_cut_lengths = int(input("How many different cut lengths are there? "))
for cut_length in range(num_of_cut_lengths):
length = float(input("What is the length of the cut (in inches)? "))
qty = int(input("How many " + str(length) + " in. cuts are needed? "))
Order.purchase_lines.append([(length + tolerance), qty])
def generate_all_possible_cuts():
"""Generates an array of every possible way to cut a single piece of stock material"""
first_possible_cut = Order.generate_first_possible_cut(Order.purchase_lines)
another_cut_possible = Order.determine_if_another_cut_possible(first_possible_cut)
previous_cuts = first_possible_cut
while another_cut_possible:
next_cuts = Order.generate_next_possible_cut(previous_cuts)
previous_cuts = Order.append_to_all_possible_cuts(next_cuts)
another_cut_possible = Order.determine_if_another_cut_possible(previous_cuts)
def generate_first_possible_cut(purchase_lines):
"""Using the cut lengths and quantities need, cutting the most pieces possible out of the stock material, starting with the first cut length entered, until the material has remainder of 0 or all cutting lengths have been attempted."""
possible_cut_length_and_qtys = []
remaining_material_length = Order.starting_material_length
for line in purchase_lines:
possible_cut_length = line[0]
max_qty = line[1]
possible_qty = int(remaining_material_length // possible_cut_length)
if possible_qty >= 0 and remaining_material_length - (possible_cut_length * possible_qty) >= 0:
if possible_qty > max_qty:
possible_cut_length_and_qtys.append([possible_cut_length, max_qty])
remaining_material_length -= possible_cut_length * max_qty
else:
possible_cut_length_and_qtys.append([possible_cut_length, possible_qty])
remaining_material_length -= possible_cut_length * possible_qty
Order.remaining_material_length = remaining_material_length
return copy.deepcopy(possible_cut_length_and_qtys)
def determine_if_another_cut_possible(previous_cuts):
"""Determines if another cut is possible. Returns True if possible, False if not possible."""
for cut in previous_cuts:
cut_qty = cut[1]
if cut_qty > 0:
return(True)
break
else:
return(False)
def generate_next_possible_cut(previous_cuts):
"""Using the previous counts, generates the next possible cut."""
index_of_lowered_digit, lowered_cuts = Order.lower_smallest_digit_possible(previous_cuts)
Order.increase_remaining_material_length(index_of_lowered_digit)
next_cuts = Order.use_remaining_stock(index_of_lowered_digit, lowered_cuts)
return copy.deepcopy(next_cuts)
def append_to_all_possible_cuts(next_cuts):
"""Appends the next possible way to cut the material to the array \"all_possible_cuts\" """
Order.all_possible_cuts.append(next_cuts[:])
previous_cuts = next_cuts
return copy.deepcopy(previous_cuts)
def lower_smallest_digit_possible(previous_cuts):
"""Using the previous counts, generates the next possible cut."""
current_cut_index = len(previous_cuts) - 1
while current_cut_index >= 0:
if previous_cuts[current_cut_index][1] > 0:
previous_cuts[current_cut_index][1] -= 1
break
else:
current_cut_index -= 1
return(current_cut_index, copy.deepcopy(previous_cuts))
def increase_remaining_material_length(index_of_lowered_digit):
"""Using the previous counts, generates the next possible cut."""
Order.remaining_material_length += Order.purchase_lines[index_of_lowered_digit][0]
def use_remaining_stock(index_of_lowered_digit, lowered_cuts):
"""Using the previous counts, generates the next possible cut."""
current_index = index_of_lowered_digit + 1
while current_index < len(lowered_cuts):
if Order.remaining_material_length >= lowered_cuts[current_index][0]:
qty = int(Order.remaining_material_length // lowered_cuts[current_index][0])
lowered_cuts[current_index][1] += qty
Order.remaining_material_length -= lowered_cuts[current_index][0] * qty
current_index += 1
return copy.deepcopy(lowered_cuts)
Order.get_order_information()
Order.generate_all_possible_cuts()
print(Order.all_possible_cuts)
# test with: 144, 2, 19, 15, 16, 30