HJ98 自动售货系统 模拟(用类实现模拟)

Posted Aneverforget

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HJ98 自动售货系统 模拟(用类实现模拟)相关的知识,希望对你有一定的参考价值。

模拟主要考的是类的组织与实现。

#其中非传入参数可以不作为实例变量,有个问题就是在后面方法调用参数需要另外传入变量。

#如果一个方法作为类参数,在方法中使用需要用类名的方法引用。

如本体,若字典d放入类中,作为类变量,则引用时形式为sale.d

作为实例变量,引用时形式为self.d

#模拟一个自动售货系统,

实现投币,购买,退币,查询库存商品,查询存钱盒信息功能

 

实现思路:

#初始化参数:

商品数量,价格,纸币面额,张数。

#退币原则:

纸币张数最少,若零钱不足,因尽最大可能退币减少顾客损失。

该纸币面额设置符合贪心算法,因此采用贪心算法。

#投币说明

投币余额:每次投入面额累加到投余额。

存钱盒:投币后存钱盒面额相应增加,也就是可找零的钱

#退余额

退币余额遵循退币原则,退币成功后退币余额清0,

同时扣除存钱盒相应金额

 

购买商品操作说明:

一次只可以买一件,购买成功后,商品数量减1,投币余额扣除本次价格

操作说明(输入说明):

命令字与第一个参数间使用一个空格分隔,多条命令采用分号隔开

不考虑非法输入

 \'\'\'
 测试案例
 输入
 r 22-18-21-21-7-20 3-23-10-6;c;q0;p 1;b A6;c;b A5;b A1;c;q1;p 5;
 输出
 S001:Initialization is successful
 E009:Work failure
 E010:Parameter error
 S002:Pay success,balance=1
 E008:Lack of balance
 1 yuan coin number=1
 2 yuan coin number=0
 5 yuan coin number=0
 10 yuan coin number=0
 E008:Lack of balance
 E008:Lack of balance
 E009:Work failure
 E010:Parameter error
 S002:Pay success,balance=5
 \'\'\'
 class sale():    #一个自动售货系统
     def __init__(self,init1,init2):
         self.num=0
         self.temp=[2,3,4,5,8,6]#对应商品价格
         self.init1=list(map(int,init1))#对应商品数量
         self.init2=list(map(int,init2))[::-1]#1,2,5,10面额数目取反10,5,2,1
         self.dnum=10:0,5:1,2:2,1:3#获取面额数目列表下标
         self.l1=[]#退给顾客的零钱
         self.goods=[\'A1\',\'A2\',\'A3\',\'A4\',\'A5\',\'A6\']
     def pay(self,num):
         if num!=1 and num!=2 and num!=5 and num!=10:
             print(d[\'E002\'])
         elif self.init2[2]*2+self.init2[3]<num:
             print(d[\'E003\'])
         elif sum(self.init1)==0:
             print(d[\'E005\'])
         else:
             self.num=self.num+num           #可用余额
             self.init2[self.dnum[num]]+=1 #存钱数列数目加1
             X=self.num
             print(d[\'S002\'].format(X))
     def buy(self,good):
         self.good=good
         if self.good not in self.goods:
             print(d[\'E006\'])
         elif self.init1[self.goods.index(self.good)]==0:
             print(d[\'E007\'])
         elif self.num<self.temp[self.goods.index(self.good)]:
             print(d[\'E008\'])
         else:            
             self.num=self.num-self.temp[self.goods.index(self.good)]#剩余钱币减少
             X=self.num
             print(d[\'S003\'].format(X))
     def change(self):    
         self.l1=[]
         while self.num>=1:
             if self.num//10>0:   
                 if self.init2[self.dnum[10]]>=self.num//10:
                     self.init2[self.dnum[10]]-=self.num//10#存钱盒数列数目减少
                     self.l1.append(self.num//10)
                     self.num-=self.num//10*10
                 else:
                     self.l1.append(self.init2[self.dnum[10]])
                     self.num-=self.init2[self.dnum[self.num]]*10
                     self.init2[self.dnum[10]]=0#存钱盒数列数目减少
             else:
                 self.l1.append(0)
             if self.num//5>0:
                 if self.init2[self.dnum[5]]>=self.num//5:
                     self.init2[self.dnum[5]]-=self.num//5#存钱盒数列数目减少
                     self.l1.append(self.num//5)
                     self.num-=self.num//5*5
                 else:
                     self.l1.append(self.init2[self.dnum[5]])
                     self.num-=self.init2[self.dnum[5]]*5
                     self.init2[self.dnum[5]]=0#存钱盒数列数目减少
             else:
                 self.l1.append(0)
             if self.num//2>0:
                 if self.init2[self.dnum[2]]>=self.num//2:
                     self.init2[self.dnum[2]]-=self.num//2#存钱盒数列数目减少
                     self.l1.append(self.num//2)
                     self.num-=self.num//2*2
                 else:
                     self.l1.append(self.init2[self.dnum[2]])
                     self.num-=self.init2[self.dnum[2]]*2
                     self.init2[self.dnum[2]]=0#存钱盒数列数目减少
             else:
                 self.l1.append(0) 
             if self.num>0:
                 if self.init2[self.dnum[1]]>=self.num:
                     self.init2[self.dnum[1]]-=self.num#存钱盒数列数目减少
                     self.l1.append(self.num)
                     self.num-=self.num#全部找零
                 else:
                     #self.l1.append(self.init2[self.dnum[self.num]])
                     self.l1.append(self.num)#退币数量
                     self.init2[self.dnum[1]]=0#存钱盒数列数目减少 #顾客损失钱
             else:
                 self.l1.append(0)                
     def withdrawc(self):
         if self.num<=0:
             print(d[\'E009\'])
         else:
             self.change()             #在类中引用类方法,self变量不需要传入
             self.out=self.l1
             self.output=f"1 yuan coin number=self.out[3];\\
 2 yuan coin number=self.out[2];\\
 5 yuan coin number=self.out[1];\\
 10 yuan coin number=self.out[0]".split(";")
             for i in self.output:
                 print(i)
     def query(self,p):
         self.forq=list(zip(self.goods,self.temp,self.init1))
         if p!=\'0\' or p!=\'1\':
             print(d[\'E010\'])
         elif p==\'0\':
             for i in self.forq:
                 print(" ".join(str,i))
         elif p==\'1\':
             #self.init2
             self.output=f"1 yuan coin number=self.init2[3];\\
 2 yuan coin number=self.init2[2];\\
 5 yuan coin number=self.init2[1];\\
 10 yuan coin number=self.init2[0]".split(";")
             for i in self.output:
                 print(i)
 #提示语词典
 d="S001":"S001:Initialization is successful",
    "S002":"S002:Pay success,balance=0",
    "S003":"S003:Buy success,balance=0",
 "E002":"E002:Denomination error",
 "E003":"E003:Change is not enough, pay fail",
 "E005":"E005:All the goods sold out",
 "E006":"E006:Goods does not exist",
 "E007":"E007:The goods sold out",
 "E008":"E008:Lack of balance",
 "E009":"E009:Work failure",
 \'E010\':\'E010:Parameter error\'    
 #处理输入
 never=input()
 #never=\'r 27-29-1-29-17-8 3-6-27-28;b A5;c;p 10;p 2;c;q1;c;q0;b A3;b A4;c;q0;b A1;b A6;q1;p 10;b A6;b A5;p 1;b A5;c;c;b A2;p 1;p 1;p 10;\' 
 l=never.split(";")
 l.remove(\'\')
 a=l[0].split()
 if a[0]==\'r\':
     print(d[\'S001\'])
 else:
     print(\'ERROR\')
 init1=list(map(int,a[1].split("-")))
 init2=list(map(int,a[2].split("-")))
 inp1=[]
 for i in l[1:]: 
     try:
         inp1.append(i.split())
     except:
         inp1.append([i])
 inst=sale(init1,init2)
 #print(inp1)
 for i in inp1:
     if i[0]==\'p\':
         inst.pay(int(i[1]))     
         #print(int(i[1]))
     elif i[0]==\'b\':        
         inst.buy(i[1])
     elif i[0]==\'c\':
         inst.withdrawc()
     elif \'q\' in i[0]:
         #print(i)
         try:
             temp=i[1]
             inst.query(temp)
         except:
             inst.query(\'2\')
         

 

华为机试HJ98:自动售货系统

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

题目描述:

1 总体说明

考生需要模拟实现一个简单的自动售货系统,实现投币、购买商品、退币、查询库存商品及存钱盒信息的功能。

系统初始化时自动售货机中商品为6种商品,商品的单价参见1.1规格说明,存钱盒内放置1元、2元、5元、10元钱币,商品数量和钱币张数通过初始化命令设置,参见2.1 系统初始化。

1.1规格说明

1. 商品:每种商品包含商品名称、单价、数量三种属性,其中商品名不重复。考生不能修改商品名称和单价,初始化命令设置商品数量。这些信息在考试框架中进行定义,考生在实现功能代码时可直接使用。

商品 名称

单价

数量

A12X
A23X
A34X
A45X
A58X
A66X

2. 存钱盒信息:钱币面额、张数两种属性。初始化命令设置各种面额钱币张数。这些信息在考试框架中进行定义,考生在实现功能代码时可直接使用。

钱币面额

张数

10元

X

5元

X
2元X
1元X

3. 退币原则 

1) 根据系统存钱盒内钱币的 信息 ,按钱币总张数最少的原则进行退币。

2) 如果因零钱不足导致不能退币,则尽最大可能退币,以减少用户损失。

例如:假设存钱盒内只有4张2元,无其它面额钱币。如果需要退币7元,系统因零钱不足无法退币,则继续尝试退币6元,最终系统成功退币3张2元,用户损失1元钱币。

4. 投币操作说明:每次投币成功,投入的钱币面额累加到投币余额;同时,本次投入的钱币放入存钱盒中,存钱盒相应面额钱币增加。

5. 投币余额:指当前自动售货机中用户剩余的可购买商品的钱币总额;例如:投入2元面额的钱币,投币余额增加2元;购买一件价格2元的商品,投币余额减少2元;

6. 退币操作说明:退币操作需要遵守 退币原则 ;退币成功后,投币余额清零,同时扣除存钱盒相应的金额。

7. 购买商品操作说明:一次仅允许购买一件商品;购买商品成功后,自动售货机中对应商品数量减1,投币余额扣除本次购买商品的价格。

2 操作说明

命令字与第一个参数间使用一个空格分隔,多条命令采用分号隔开。考试系统会对输入命令格式进行处理,考生不需要关注输入命令格式的合法性,只需要实现命令处理函数。

2.1 系统初始化

命令格式

r A1 数量 -A2 数量 -A3 数量 -A4 数量 -A5 数量 -A6 数量 元张数 -2 元张数 -5 元张数 -10 元张数

参数名称

参数说明

类型

取值范围

A1数量

商品A1数量

整数

[0,30]

A2数量

商品A2数量

整数

[0,30]

A3数量

商品A3数量

整数

[0,30]

A4数量

商品A4数量

整数

[0,30]

A5数量

商品A5数量

整数

[0,30]

A6数量

商品A6数量

整数

[0,30]

1元张数

面额1元钱币张数

整数

[0,30]

2元张数

面额2元钱币张数

整数

[0,30]

5元张数

面额5元钱币张数

整数

[0,30]

10元张数

面额10元钱币张数

整数

[0,30]

商品和各种面额钱币取值范围只是作为初始化命令的限制,其它场景下不限制取值范围;考试框架已经实现取值范围的检查,考生不需要关注。

功能说明:设置自动售货机中商品数量和存钱盒各种面额的钱币张数;

约束说明:系统在任意阶段均可执行r初始化系统;考生不需要关注参数的合法性,不需要关注增加或缺少参数的场景;

输出说明:输出操作成功提示(执行完r命令后系统会自动输出操作结果,考生不需要再次调用输出函数),例:

命令输出含义
r 6-5-4-3-2-1 4-3-2-1;S001:Initialization is successful初始化成功

2.2 投币

命令格式钱币面额

功能说明

(1) 如果投入非1元、2元、5元、10元的钱币面额(钱币面额不考虑负数、字符等非正整数的情况),输出“E002:Denomination error”;

(2) 如果存钱盒中1元和2元面额钱币总额小于本次投入的钱币面额,输出“E003:Change is not enough, pay fail”,但投入1元和2元面额钱币不受此限制。

(3) 如果自动售货机中商品全部销售完毕,投币失败。输出“E005:All the goods sold out”;

(4) 如果投币成功,输出“S002:Pay success,balance=X”;

约束说明

(1) 系统在任意阶段都可以投币;

(2) 一次投币只能投一张钱币;

(3) 同等条件下,错误码的优先级:E002 > E003 > E005;

输出说明:如果投币成功,输出“S002:Pay success,balance=X”。

例:

命令

输出

p 10;

S002:Pay success,balance=10

2.3 购买商品

命令格式商品名称

功能说明

(1) 如果购买的商品不在商品列表中,输出“E006:Goods does not exist”;

(2) 如果所购买的商品的数量为0,输出“E007:The goods sold out”;

(3) 如果投币余额小于待购买商品价格,输出“E008:Lack of balance”;

(4) 如果购买成功,输出“S003:Buy success,balance=X”;

约束说明

(1) 一次购买操作仅能购买一件商品,可以多次购买;

(2) 同等条件下,错误码的优先级:E006 > E007 > E008;

输出说明:

如果购买成功,输出“S003:Buy success,balance=X”。

例:

命令

输出

b A1;

S003:Buy success,balance=8

2.4 退币

命令格式c

功能说明

(1) 如果投币余额等于0的情况下,输出“E009:Work failure”;

(2) 如果投币余额大于0的情况下,按照 退币原则 进行“找零”,输出退币信息;

约束说明

(1) 系统在任意阶段都可以退币;

(2) 退币方式必须按照 退币原则 进行退币;

输出说明:如果退币成功,按照 退币原则 输出退币信息。

例,退5元钱币:

命令

输出

c;

1 yuan coin number=0

2 yuan coin number=0

5 yuan coin number=1

10 yuan coin number=0

2.5 查询

命令格式q 查询类别

功能说明

(1) 查询自动售货机中商品信息,包含商品名称、单价、数量。 根据商品数量从大到小进行排序;商品数量相同时,按照商品名称的先后顺序进行排序 

例如:A1的商品名称先于A2的商品名称,A2的商品名称先于A3的商品名称。

(2) 查询存钱盒信息,包含各种面额钱币的张数;

(3) 查询类别如下表所示:

查询类别

查询内容

0

查询商品信息

1查询存钱盒信息

如果“查询类别”参数错误,输出“E010:Parameter error”。“查询类别”参数错误时,不进行下面的处理;

输出说明

“查询类别”为0时,输出自动售货机中所有商品信息(商品名称单价数量)例:

命令

输出

q 0;

A1 2 6

A2 3 5

A3 4 4

A4 5 3

A5 8 2

A6 6 0

“查询类别”为1时,输出存钱盒信息(各种面额钱币的张数),格式固定。例:

命令

输出

q 1;

1 yuan coin number=4

2 yuan coin number=3

5 yuan coin number=2

10 yuan coin number=1

输入描述:

依照说明中的命令码格式输入命令。

输出描述:

输出执行结果

示例:

输入:

r 22-18-21-21-7-20 3-23-10-6;c;q0;p 1;b A6;c;b A5;b A1;c;q1;p 5;
r 28-12-11-1-16-10 19-30-8-11;b A1;p 1;

输出:

S001:Initialization is successful
E009:Work failure
E010:Parameter error
S002:Pay success,balance=1
E008:Lack of balance
1 yuan coin number=1
2 yuan coin number=0
5 yuan coin number=0
10 yuan coin number=0
E008:Lack of balance
E008:Lack of balance
E009:Work failure
E010:Parameter error
S002:Pay success,balance=5
S001:Initialization is successful
E008:Lack of balance
S002:Pay success,balance=1

解题思路:

这题是个应用题,制作一个简易版的自动售货系统,可以用面向对象来做,建立商品、存钱盒和售货系统的类,然后实现功能即可。题目没有太大难度,就是比较啰嗦。有一位牛客上来自西北工业大学的gingkg同学,他写的代码非常整洁和直观,所以我在此注明并分享其代码。他写了三个类,用于描述商品、存钱盒和售货系统的相关参数、属性和功能。

测试代码:

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
// 商品类
class Goods
{
private:
    string name;
    int price;
    int num;
 
public:
    Goods(){
        name = "NONE";
        price = 0;
        num = 0;
    }
    Goods(string str, int i, int j){
        name = str;
        price = i;
        num = j;
    }
    void Init(int j){
        num = j;
    }
    string& NAME(){return name;}
    int& PRICE(){return price;}
    int& NUM(){return num;}
    void addGoods(int i = 1){
        num += i;
    }
    void reduceGoods(int i = 1){
        num -= i;
    }
};
// 存钱盒类
class SavingBox
{
private:
    unordered_map<int, int> coins;
public:
    SavingBox(){
        coins[1] = 0;
        coins[2] = 0;
        coins[5] = 0;
        coins[10] = 0;
    }
    SavingBox(unordered_map<int, int>& index){
        for(auto iter = index.begin(); iter != index.end(); iter++){
            coins[iter->first] = iter->second;
        }
    }
    unordered_map<int, int>& COINS(){return coins;};
    void Init(unordered_map<int, int>& index){
        for(auto iter = index.begin(); iter != index.end(); iter++){
            coins[iter->first] = iter->second;
        }
    }
    void addCoin(int i, int j=1){
        coins[i] += j;
    }
    void reduceCoin(int i, int j=1){
        coins[i] -= j;
    }
    int getCoinNum(int i){
        if(coins.count(i)){
            return coins[i];
        }else{
            throw("输入错误");
        }
    }
};
// 售货系统类
class VendingSystem
{
private:
    vector<string> names = {"A1", "A2", "A3", "A4", "A5", "A6"};
    vector<int> prices = {2,3,4,5,8,6};
    vector<Goods> shops;
    vector<int> coins = {1,2,5,10};
    SavingBox box;
    int balance;  // 投币余额
 
public:
    VendingSystem(){
        for(int i =0; i < 6; i++){
            shops.push_back(Goods(names[i], prices[i], 0));
        }
        unordered_map<int, int> index;
        for(int k = 0; k < int(coins.size()); k++){
            index[coins[k]] = 0;
        }
        box = SavingBox(index);
        balance = 0;
    }
    void Run(string str){
        if(str[0] == 'r'){
            Init(str);
        }else if(str[0] == 'p'){
            Pay(str);
        }else if(str[0] == 'b'){
            Buy(str);
        }else if(str[0] == 'c'){
            Change();
        }else if(str[0] == 'q'){
            Query(str);
        }else{
            throw("输入错误");
        }
    }
    void Init(string str){
        balance = 0;
 
        // 22-18-21-21-7-20 3-23-10-6
        str = str.substr(2, str.size()-2);
        string initGoodCmd = str.substr(0, str.find(' '));
        string initBoxCmd = str.substr(str.find(' ')+1, str.size()-str.find(' ')-1);
 
        vector<int> nums;
        int i = 0, j= 0;
        while(j < int(initGoodCmd.size())){
            if(initGoodCmd[j] == '-'){
                nums.push_back(atoi(initGoodCmd.substr(i, j-i).c_str()));
                i = j+1;
            }
            j++;
        }
        nums.push_back(atoi(initGoodCmd.substr(i, j-i).c_str()));
        for(int k = 0; k < 6; k++){
            shops[k].Init(nums[k]);
        }
 
        nums.clear();
        i = 0, j = 0;
        while(j < int(initBoxCmd.size())){
            if(initBoxCmd[j] == '-'){
                nums.push_back(atoi(initBoxCmd.substr(i, j-i).c_str()));
                i = j+1;
            }
            j++;
        }
        nums.push_back(atoi(initBoxCmd.substr(i, j-i).c_str()));
        unordered_map<int, int> index;
        for(int k = 0; k < int(coins.size()); k++){
            index[coins[k]] = nums[k];
        }
        box.Init(index);
 
        cout << "S001:Initialization is successful" << endl;
    }
    void Pay(string str){
        //获取面额
        int money = atoi(str.substr(2, str.size()-2).c_str());
        if(!count(coins.begin(), coins.end(), money)){
            cout << "E002:Denomination error" << endl;
            return;
        }
        if(money == 5 || money == 10){
            if((box.getCoinNum(1)+box.getCoinNum(2)*2) < money){
                cout << "E003:Change is not enough, pay fail" << endl;
                return;
            }
        }
        //查询剩余商品数量
        bool flag = true;
        for(auto shop: shops){
            if(shop.NUM() > 0){
                flag = false;
                break;
            }
        }
        if(flag){
            cout << "E005:All the goods sold out" << endl;
            return;
        }
        // 投币成功
        balance += money;
        box.addCoin(money);
        cout << "S002:Pay success,balance=" << balance << endl;
    }
    void Buy(string str){
        string name = str.substr(2, str.size()-1);
        if(!count(names.begin(), names.end(), name)){
            cout << "E006:Goods does not exist" << endl;
            return;
        }
        Goods& shop = shops[distance(names.begin(),find(names.begin(), names.end(), name))];
        if(shop.NUM() == 0){
            cout << "E007:The goods sold out" << endl;
            return;
        }
        if(shop.PRICE() > balance){
            cout << "E008:Lack of balance" << endl;
            return;
        }
        //购买成功
        shop.reduceGoods();
        balance -= shop.PRICE();
        cout << "S003:Buy success,balance=" << balance << endl;
    }
    void Change(){
        if(balance == 0){
            cout << "E009:Work failure" << endl;
            return;
        }
        vector<int> info(coins.size());
        for(int i = coins.size()-1; i >= 0; i--){
            int coin = coins[i];
            while(balance >= coin && box.getCoinNum(coin) > 0){
                balance -= coin;
                box.reduceCoin(coin);
                info[i]++;
            }
        }
        for(int i = 0; i < int(info.size()); i++){
            cout << coins[i] << " yuan coin number=" << info[i] << endl;
        }
    }
    void Query(string str){
        if(str == "q 0"){
            // 根据商品数量从大到小排序
            vector<Goods> shops_ = shops;
            sort(shops_.begin(), shops_.end(), cmp);
            for(auto shop: shops_){
                cout << shop.NAME() << " " << shop.PRICE() << " " << shop.NUM() << endl;
            }
            return;
        }
        if(str == "q 1"){
            for(int coin: coins){
                cout << coin << "yuan coin number=" << box.getCoinNum(coin) << endl;
            }
            return;
        }
        cout << "E010:Parameter error" << endl;
    }
    static bool cmp(Goods g1, Goods g2){
        return g2.NUM() < g1.NUM();
    }
};
int main()
{
    string str;
    vector<string> cmds;
    VendingSystem sys;
 
    while(getline(cin, str)){
        int i = 0, j = 0;
        cmds.clear();
        while(j < int(str.size())){
            if(str[j] == ';'){
                cmds.push_back(str.substr(i, j-i));
                i = j + 1;
            }
            j++;
        }
        for(unsigned int i = 0; i < cmds.size(); i++){
            //cout << cmds[i] << endl;
            sys.Run(cmds[i]);
        }
    }
}

以上是关于HJ98 自动售货系统 模拟(用类实现模拟)的主要内容,如果未能解决你的问题,请参考以下文章

华为机试HJ98:自动售货系统

#yyds干货盘点# 解决华为机试:自动售货系统

windows98

语言模拟ATM自动取款机系统

啥?虚拟现实技术已经应用到自动化仓库? | 基于unity实现的自动化仓库模拟监控系统

模拟银行自动终端系统