如何从数组

时间:2019-12-23 12:22:50

标签: python arrays python-3.x

您将被油漆到A大小的地板上。从4个主要区域中将有12个油漆桶 颜色各有3种阴影(即总共12个桶)。铲斗尺寸,或更具体地说, 以下阵列给出了可以从每种阴影绘制的区域数量。 相同的原色的不同阴影显示在同一行中。

  • [12,23,14]
  • [10,30,15]
  • [16,22,35]
  • [14、24、20]

问题与约束

您需要选择4种阴影来绘制地板区域;

  1. 整个地面应涂漆;也不允许阴影重叠
  2. 已为最终绘画选择了每种原色的“只有一个”阴影
  3. 尽量减少浪费(即假设我们打开并使用水桶后, 剩余的将被丢弃)

实施python程序来回答以下问题;

Q1。满足上述约束(如果A = 100)的颜色阴影(或色块)
Q2。上述情况下的浪费量
Q3。如果A = 90,那么Q1和Q2的解决方案是什么?

注意:您可以使用以下符号来引用上图中的每个阴影。

R-行索引
C-列索引
(r,c)-第(r + 1)行和第(c + 1)列的阴影
例如(0,0)-> 12,(0,1)-> 23,(1,2)-> 15,等等

这样,可以以[(0,1),(1,2),(2,0),(3,2)]格式给出Q1的答案


如果用户输入100,则系统应显示其坐标最接近100的颜色代码区域

示例

Enter your Area = 100
100 ~ 101(sum of areas 12+30+35+24, There for 101 is the closet number to 100)

Shades          = [12 30 35 24]
Cordinates of shades = (0,0)(1,1)(2,2)(3,1)

这是我的应答代码

import numpy as np
import itertools

colors = np.array([[12, 23, 14], [10, 30, 15], [16, 22, 35], [14, 24, 20]])

max_tot = 0

#get total of all integers which are in array
for i in range(len(colors)):
    max_tot = max_tot + max(colors[i])

#Enter Area
area = int(input("Enter your Area = "))

if(area > max_tot):
    print("Area is too long. Don't have enough paints for painting")
elif(area <= 0):
    print("Wrong area")
else:
    #get shades which are given lowest minimum wastage
    for element in itertools.product(*colors):
        if(sum(element) >= area):
            x = sum(element)
            if(x <= max_tot):
                max_tot = x
                el = np.array(element)

    print()
    print("sum of shades   =", max_tot)
    print("minimum wastage =" , max_tot - area)
    print("Shades          =", el)
    print("Cordinates of shades = " ,end ='')

    #get coordinates using manual method
    for i in range(4):
        g,h = np.where(colors == el[i])
        print("(" ,g[0],",", h[0], ")", sep=' ', end='', flush=True)

输出-:

Enter your Area = 100

sum of shades   = 101
minimum wastage = 1
Shades          = [12 30 35 24]
Cordinates of shades = ( 0 , 0 )( 1 , 1 )( 2 , 2 )( 3 , 1 )

您可以看到我有12 30 35 24的坐标是手动类型。那不是一个好的编程方法。

如何直接(使用更好的方法)获得该坐标?

请注意,我已经回答了所有问题。我想要一个更好的第三季度答案

1 个答案:

答案 0 :(得分:0)

优化搜索的唯一可能方法是在每次选择后删除重复的和值。很容易检查81种可能的浪费中是否有45种不同的浪费值:

len(set(sum(el) for el in product(*colors)))
Out[99]: 45
len(list(sum(el) for el in product(*colors)))
Out[100]: 81

其中几乎有一半是根据sum复制的,这对于您的计算来说是不必要的权重。但这并不是很大的速度。这很大程度上取决于您运行代码的数据质量,主要是每个列表的值有多大以及列表的数量。

我整理了您的代码以使其更加高效和可读:

import numpy as np
from itertools import product

def get_area(max_tot):
    # Asks to enter area and returns it or raises exception if it's wrong
    # max_tot is maximum possible area
    try: 
        area = int(input("Enter your Area = "))
    except ValueError:
        raise ValueError('Area is not a number')
    if area > max_tot:
        raise ValueError("Area is too long. Don't have enough paints for painting")
    elif area <= 0:
        raise ValueError("Wrong area")
    else:
        return area

def get_shades(colors, area, max_tot):
    #get shades which are given lowest minimum wastage
    for element in product(*colors):
        sum_of_element = sum(element) # assigning it there to avoid double calculation
        if area <= sum_of_element <= max_tot: # double comparison is possible in Python 
            max_tot = sum_of_element
            el = np.array(element)
    return el

colors = np.array([[12, 23, 14], [10, 30, 15], [16, 22, 35], [14, 24, 20]])
max_tot = np.sum(np.max(colors, axis=1))
area = get_area(max_tot)  
el = get_shades(colors, area, max_tot)

print()
print("sum of shades   =", max_tot)
print("minimum wastage =" , max_tot - area)
print("Shades          =", el)
print("Cordinates of shades = " ,end ='')

#get coordinates using manual method
for i in range(4):
    g,h = np.where(colors == el[i])
    print("({}, {})".format(g[0], h[0]), sep=' ', end=' ', flush=True)

您的代码的“核心”在get_shades函数中。我删除了sum(element)的重复计算,并且还将一行进行两次比较以使其更具可读性。顺便说一下,可以按如下所示以100%函数样式重写get_shades函数:

def get_shades(colors, area, max_tot):
    # functional version of get_shades
    def cmp(x):
        # compares items based on their sum; bad items are largest by default
        s = sum(x)
        if s >= area: return s
        else: return max_tot + 1
    return min(product(*colors), key = cmp)

但是,正如您提到的那样,这还不够。您可能希望通过在每次选择后删除重复的总和来减少它:

[[12, 23, 14], [10, 30, 15]] -> [22, 24, 27, 29, 33, 38, 42, 44, 53] # 9 distinct sum values
[[22, 24, 27, 29, 33, 38, 42, 44, 53], [16, 22, 35]] -> # 24 distinct sum values
[[...], [14, 24, 20]] -> 45 distinct sum values

这是reduce方法设计的一个很好的例子。每次迭代之后,它将获取最后的结果,对下一项进行计算,然后将其替换为新的结果。可以使用以下方式捕获总和的所有45个值:

wastages = reduce(lambda x,y: set(sum(n) for n in product(x, y)), colors)

并通过以下方法找到所需的最低金额:

min(wastages, key = cmp)

其中cmp的定义方式如下:

def cmp(x):
    if x >= area: return x
    else: return max_tot + 1

但是会出现另一个大问题:阴影与它们的总和不同,不会保存在内存中。为了保留阴影和总和之间的映射,需要额外的功能。这就需要操作列表的高级方法,这似乎很慢而不是加快。我将它们排除在范围之外,因为映射需要更多困难的算法,并且仅当您的数据大于您发布的数据时,它们才有用。