2021华为软挑赛题_思路分析——实时更新,做多少更多少(四)

2021华为软挑赛题_思路分析——实时更新,做多少更多少(四)



本专栏食用建议

  • 随着文章越更越多,本专栏的内容到底该如何食用,笔者在此做出如下建议,望能为参赛的诸位节省宝贵的时间和精力:
  • 本专栏内容第一篇为思路的初步探索,适合没有多少思路或者对赛题把握比较模糊的朋友。当然,在赛程后期,有朋友已经做完提交想要在温故一遍赛题的话,亦可回顾此文
  • 至于第二篇文章,确实建议大家可以详细浏览,包含着鄙人对于此题的主要思路,至少相比于同类文章,个人认为此想法是最为可能落地的一种(暂不谈算法效率)。
  • 接下来的三篇文章(后面陆续如此),主要是对第二篇文章的代码实现,可尽可能地去读最新的代码,毕竟,写着写着发现之前问题的事情也不是头一次发生,望诸位见谅~
  • 当然,以上不过是鄙人的小小建议,若有朋友希望能够完全的去理解鄙人解题的全部心路历程,逐篇阅读亦未尝不可~

前言

  • 最近代码越更越长,都放到一篇怕朋友们引起不适,故如此布局文章,谅解~
  • 本文为在上篇文章的基础上,将“2021华为软挑赛题_思路分析——实时更新,做多少更多少(二)”中购买分配算法的偏数据处理部分(具体哪部分文中介绍)。
  • 代码越更越长,鄙人尽力加全注释,但知道仍难解决朋友的全部疑惑,这里只能劝朋友多调试,毕竟不手写还是很难完全理解。
  • 不过,大家目的不同,若果只是借鉴,请自行取用~

3月16日更新


1.今日更新——购买分配算法前期数据处理

2021华为软挑赛题_思路分析——实时更新,做多少更多少(二)
下方的代码,在昨日的基础上增添了shoppingAndDistribution()购买分配算法,解决了购买分配算法在前期的数据处理问题,数据处理的思路做个归纳:

  • 将hostListAll服务器列表按照hostXingJiaBi性价比排序。
  • hostListAll服务器列表按照核内比分类(单写了一个方法classifyByCoreMemBi()自认为是命名鬼才,哈哈),分成hostCoreMemBiBigList(大于1), hostCoreMemBiSmallList(小于1)。
  • 匹配dayListAll每日请求中虚拟机型号与vmListAll虚拟机总表中的虚拟机型号,将从vmListAll中匹配到的vmCpuNum,vmMemSize,vmDoubleOrNot,vmCoreMemBi增添addRequireList中的数据。
  • 将dayListAll每一个元素的addRequireList按单双节点分类。
  • 调用DayRequire类内置averageCoreMemBi()方法计算平均核内比。
  • 调用sortByAverageCoreMemBi()方法,判断单、双节点请求列表的平均核内比是否大于1,若大于1,将两个列表按照vmCpuNum(核数)将vm升序排列; 否则,按照vmMemSize(内存容量)升序排列。
  • 到此截止,望朋友可以享受思考的过程,加油~
# 代码解决2021华为软件挑战赛中的数据输入、购买分配算法前期数据处理问题
# 所有注释为了便于说明,以training-1.txt中的数据为例
# 代码中注释掉的print,多数可自行解封看看预期结果
# !!!*****!!! 为昨日代码的出错点
# 技艺不精,私事繁忙,照顾不周,多担待!

# 导入numpy库
import numpy

# 服务器类
class Host:
    hostType = ''           #服务器类型
    hostCpuNum = 1          #服务器CPU数
    hostMemSize = 1         #服务器内存容量
    hostHardWareCost = 1    #服务器硬件开销
    hostDayCost = 1         #服务器每日开销
    hostXingJiaBi = 1       #服务器性价比:(硬件开销*(核数/核数+内存容量)/核数) + (硬件开销*(内存容量/核数+内存容量)/内存容量)
    hostCoreMemBi = 1       #服务器核内比:核数/内存容量

    # 计算性价比
    # !!!认真观察的道友应该能发现,此处公式与昨日略有不同,但与昨日数值结果相同,可自己细品,理解鄙人定义的性价比的意义!!!
    def xingJiaBi(self):
        self.hostXingJiaBi = ((self.hostHardWareCost * (self.hostCpuNum / (self.hostCpuNum + self.hostMemSize)))/ self.hostCpuNum) + ((self.hostHardWareCost * self.hostMemSize / (self.hostCpuNum + self.hostMemSize)) / self.hostMemSize)

    # 计算核内比
    def coreMemBi(self):
        self.hostCoreMemBi = self.hostCpuNum / self.hostMemSize
# 虚拟机类
class Vm:
    vmType = ''
    vmCpuNum = 1
    vmMemSize = 1
    vmDoubleOrNot = 1
    vmCoreMemBi = 1

    # 计算核内比
    def coreMemBi(self):
        self.vmCoreMemBi = self.vmCpuNum / self.vmMemSize
# 每日请求列表类——输入数据时使用
class DayRequire:
    requireNum = 0
    requireType = ''
    vmType = ''
    vmId = ''
    averageDoubleCoreMemBi = ''
    averageSingleCoreMemBi = ''

    # !!!昨日出错重点,以前一直没发现,pyhton类中定义的列表是全局变量!!!
    # 解决方法:通过初始化方法,将列表定义为self的局部变量
    def __init__(self):
        self.addRequireList = []
        self.addRequireList_Double = []    # 列表中依此为requireType, vmType, vmId,
                                           # vmCpuNum, vmMemSize, vmDoubleOrNot, vmCoreMemBi
        self.addRequireList_Single = []
        self.delRequireList = []

    # !!!增加了两个为列表赋值的函数,只为美化代码!!!
    def addRequireListAppend(self):
        self.addRequireList.append([self.requireType, self.vmType, self.vmId])

    def delRequireListAppend(self):
        self.delRequireList.append([self.requireType, self.vmId])

    # 计算每日add请求平均核内比
    def averageCoreMemBi(self):
        tempList = [require[6] for require in self.addRequireList_Double]
        self.averageDoubleCoreMemBi = numpy.mean(tempList)
        tempList = [require[6] for require in self.addRequireList_Single]
        self.averageSingleCoreMemBi = numpy.mean(tempList)

# 一次性读入全部文件
def readTxt(filename):
    try:
        f = open(filename, "r")
        line = f.read()
        return line
    finally:
        f.close()

#按核内比分类
def classifyByCoreMemBi(numpyList):
    # 核内比大于一的分一类,小于一的分一类
    posCoreMemBiBig = numpy.argwhere(numpyList > 1)
    # print(posCoreMemBiBig)
    CoreMemBiBigList = [numpyList[n[0]] for n in posCoreMemBiBig]
    posCoreMemBiSmall = numpy.argwhere(numpyList <= 1)
    CoreMemBiSmallList = [numpyList[n[0]] for n in posCoreMemBiSmall]
    return CoreMemBiBigList, CoreMemBiSmallList


def sortByAverageCoreMemBi(dayList):
    # 处理Double
    if dayList.averageDoubleCoreMemBi >= 1:
        # 取出vmCpuNum存成列表
        vmCpuNumTempList = [addRequireList_Double[3] for addRequireList_Double in dayList.addRequireList_Double]
        vmCpuNumTempList = numpy.array(vmCpuNumTempList)
        # 按照vmCpuNum升序排序
        posVmCpuNumList = numpy.argsort(vmCpuNumTempList)
        dayList.addRequireList_Double = [dayList.addRequireList_Double[n] for n in posVmCpuNumList]
        print(dayList.addRequireList_Double)
    else:
        # 取出vmMemSize存成列表
        vmMemSizeTempList = [addRequireList_Double[4] for addRequireList_Double in dayList.addRequireList_Double]
        vmMemSizeTempList = numpy.array(vmMemSizeTempList)
        # 按照vmMemSize升序排序
        posVmMemSizeList = numpy.argsort(vmMemSizeTempList)
        dayList.addRequireList_Double = [dayList.addRequireList_Double[n] for n in posVmMemSizeList]
    # 处理Single
    if dayList.averageSingleCoreMemBi >= 1:
        # 取出vmCpuNum存成列表
        vmCpuNumTempList = [addRequireList_Single[3] for addRequireList_Single in dayList.addRequireList_Single]
        vmCpuNumTempList = numpy.array(vmCpuNumTempList)
        # 按照vmCpuNum升序排序
        posVmCpuNumList = numpy.argsort(vmCpuNumTempList)
        dayList.addRequireList_Single = [dayList.addRequireList_Single[n] for n in posVmCpuNumList]
    else:
        # 取出vmMemSize存成列表
        vmMemSizeTempList = [addRequireList_Single[4] for addRequireList_Single in dayList.addRequireList_Single]
        vmMemSizeTempList = numpy.array(vmMemSizeTempList)
        # 按照vmMemSize升序排序
        posVmMemSizeList = numpy.argsort(vmMemSizeTempList)
        dayList.addRequireList_Single = [dayList.addRequireList_Single[n] for n in posVmMemSizeList]

# 购买、分配算法——数据处理部分
def shoppingAndDistribution(hostListAll, vmListAll, dayListAll):
    # 将服务器列表按照性价比排序
    # 取出hostXingJiaBi单做一个列表
    hostXingJiaBiList = [host.hostXingJiaBi for host in hostListAll]
    # print(hostXingJiaBiList)
    # 调用numpy.argsort函数排序返回下标
    hostXingJiaBiList = numpy.array(hostXingJiaBiList)
    # print(hostXingJiaBiList)
    posHostXingJiaBiList = numpy.argsort(hostXingJiaBiList)
    # print(pos)
    hostListAll = [hostListAll[n] for n in posHostXingJiaBiList]

    # 服务器按照核内比分类
    hostCoreMemBiList = [host.hostCoreMemBi for host in hostListAll]
    hostCoreMemBiList = numpy.array(hostCoreMemBiList)
    [hostCoreMemBiBigList, hostCoreMemBiSmallList] = classifyByCoreMemBi(hostCoreMemBiList)

    # 匹配每日请求中虚拟机型号与虚拟机总表中的虚拟机型号
    # 增添addRequireList的数据
    vmTypeListAll = [vm.vmType for vm in vmListAll]
    vmTypeListAll = numpy.array(vmTypeListAll)
    # 获取全部add请求的列表
    addRequireListAll = [day.addRequireList for day in dayListAll]
    # print(addRequireListAll)
    # 为dayListAll中的addRequireList增添vmCpuNum,vmMemSize,vmDoubleOrNot,vmCoreMemBi
    for i in range(len(dayListAll)):
        # 取出一日的请求
        vmTypeOneDayList = [oneRequire[1] for oneRequire in addRequireListAll[i]]
        # print(vmTypeOneDayList)
        posVmTypeListAll = [numpy.argwhere(vmTypeListAll == vmTypeOne) for vmTypeOne in vmTypeOneDayList]
        # print(posVmTypeListAll[0][0][0])
        # 为每一天的一项add请求增添vmCpuNum,vmMemSize,vmDoubleOrNot,vmCoreMemBi元素
        for j in range(len(posVmTypeListAll)):
            # print(posVmTypeListAll[j][0][0])
            temp = [vmListAll[posVmTypeListAll[j][0][0]].vmCpuNum,
                    vmListAll[posVmTypeListAll[j][0][0]].vmMemSize,
                    vmListAll[posVmTypeListAll[j][0][0]].vmDoubleOrNot,
                    vmListAll[posVmTypeListAll[j][0][0]].vmCoreMemBi]
            # print(temp)
            # print(dayListAll[i].addRequireList[0])
            dayListAll[i].addRequireList[j].extend(temp)
            # print(dayListAll[0].addRequireList[j])

            # 将addRequireList按单双节点分类
            if dayListAll[i].addRequireList[j][5] == 1:
                dayListAll[i].addRequireList_Double.append(dayListAll[i].addRequireList[j])
            else:
                dayListAll[i].addRequireList_Single.append(dayListAll[i].addRequireList[j])
        # 调用类内置方法计算平均核内比
        dayListAll[i].averageCoreMemBi()

        # 判断单、双节点请求的平均核内比是否大于1
        # 若大于1,将两个列表按照vmCpuNum(核数)将vm升序排列
        # 否则,按照vmMemSize(内存容量)升序排列
        sortByAverageCoreMemBi(dayListAll[i])

        # 到这里,对数据的处理大致已经结束
        # 文中注释掉的print,多数可自行解封看看预期结果
        # 注释部分,鄙人已经尽力,但知道仍难解决朋友的全部疑惑
        # 毕竟随着代码越更越长,不是手写的话很难完全理解
        # 但,如果能看到这里的话,说明你很认真,接下来该准备执行凑数相关的功能了
        # 明日依情况而定,一直还在商议是否要更出核心算法
        # 望朋友多多支持!


# 将输入的数据处理,输出为hostListAll, vmListAll, dayListAll列表
# hostListAll, vmListAll 分别代表服务器总表与虚拟机总表
# dayListAll中存储800天的数据,每一个列表元素为一个类(oneDay)
def inputData(allData):
    flag = 0
    for i in range(len(allData)):
        if allData[i].isdigit():
            flag += 1
            # flag=1 准备处理出服务器总表
            if flag == 1:
                hostTypeNum = int(allData[i])
                hostListAll = [allData[i + j + 1] for j in range(hostTypeNum)]
            # flag=2 准备处理出虚拟机总表
            elif flag == 2:
                vmTypeNum = int(allData[i])
                vmListAll = [allData[i + j + 1] for j in range(vmTypeNum)]
            # flag=3 接收所有天的全部请求 本页代码中的小弯弯
            elif flag == 3:
                dayNum = int(allData[i])
                flag1 = 0
                dayListAll = [0 for j in range(dayNum)] #存DayRequire类
                # 遍历800日后的全部输入 可体会一下同级下的break
                for j in range(i + 1, len(allData)):
                    if allData[j].isdigit():
                        flag1 += 1
                        # 读不懂可解开下句封印 尝试观察输出
                        # print(allData[j], allData[j+1])
                        #过滤请求类数据,接收每日请求的数值 譬如第一日142
                        if flag1 <= dayNum:
                            #新建一个类 用于接收每一天的请求数据
                            oneDay = DayRequire()
                            oneDay.requireNum = int(allData[j])
                            # 读不懂可解开下句封印 尝试观察输出
                            # print(oneDay.requireNum)
                            # 下方for循环接收每一天的请求数据 存到oneDay的类中 传给dayListAll
                            for k in range(j + 1, j + oneDay.requireNum + 1):
                                # 按逗号切分每条请求
                                tmpeList = allData[k].split(',')
                                # 切分后的数组若只有两项表明为del请求 传给oneDay.delRequireList
                                if len(tmpeList) == 2:
                                    # 清除多余空格、括号
                                    oneDay.requireType = tmpeList[0].replace('(', '')
                                    oneDay.vmId = tmpeList[1].replace(')', '').replace(' ', '')
                                    oneDay.delRequireListAppend()
                                # 切分后的数组若有三项表明为add请求 传给oneDay.addRequireList
                                elif len(tmpeList) == 3:
                                    # 清除多余空格、括号
                                    oneDay.requireType = tmpeList[0].replace('(', '')
                                    oneDay.vmType = tmpeList[1].replace(' ', '')
                                    oneDay.vmId = tmpeList[2].replace(')', '').replace(' ', '')
                                    oneDay.addRequireListAppend()
                            dayListAll[flag1 - 1] = oneDay
                # 执行完flag==3中的内容后,可直接跳出最外层for循环
                break
    # 为Host类赋值,使hostListAll中每一个元素为一个Host类
    i = 0
    for host in hostListAll:
        #分割数据去除空格、括号
        host = host.split(',')
        host[0] = host[0].replace('(', '').replace(' ', '')
        host[4] = host[4].replace(')', '').replace(' ', '')

        #赋值数据
        tmpeHost = Host()
        tmpeHost.hostType = host[0]
        tmpeHost.hostCpuNum = int(host[1])
        tmpeHost.hostMemSize = int(host[2])
        tmpeHost.hostHardWareCost = int(host[3])
        tmpeHost.hostDayCost = int(host[4])
        tmpeHost.xingJiaBi()
        tmpeHost.coreMemBi()
        hostListAll[i] = tmpeHost
        i += 1
    # 为Vm类赋值,使vmListAll中每一个元素为一个Vm类
    i = 0
    for vm in vmListAll:
        #分割数据去除空格、括号
        vm = vm.split(',')
        vm[0] = vm[0].replace('(', '').replace(' ', '')
        vm[3] = vm[3].replace(')', '').replace(' ', '')

        # 赋值数据
        tmpeVm = Vm()
        tmpeVm.vmType = vm[0]
        tmpeVm.vmCpuNum = int(vm[1])
        tmpeVm.vmMemSize = int(vm[2])
        tmpeVm.vmDoubleOrNot = int(vm[3])
        tmpeVm.coreMemBi()
        vmListAll[i] = tmpeVm
        i += 1
    i = 0

    return hostListAll, vmListAll, dayListAll

def main():
    # to read standard input
    # process
    # to write standard output
    # sys.stdout.flush()

    #以training-1.txt为示例
    filename = "training-1.txt"

    #按换行分割全部数据
    allData = readTxt(filename).split('\n')
    # 根据下一条注释可以返回分割后的数据
    # print(allData[0])
    [hostListAll, vmListAll, dayListAll] = inputData(allData)
    # 购买分配算法——仅有数据处理
    shoppingAndDistribution(hostListAll, vmListAll, dayListAll)

    # 根据下一条的输出,可显示第一天第一条请求
    # print(dayListAll[0].addRequireList[0])

if __name__ == "__main__":
    main()


总结

Ps:

  • 不知过零点更新,还算不算16日。
  • 哈哈还是参考工作时长吧!
  • 如果大家有什么好的思路,或者本文代码的不妥之处,欢迎在评论区吐槽留言~

猜你喜欢

转载自blog.csdn.net/weixin_44459972/article/details/114905133