华为机试-098-困难-HJ98.自动售货系统


一、描述

1、总体说明

  • 考生需要模拟实现一个简单的自动售货系统,实现投币、购买商品、退币、查询库存商品及存钱盒信息的功能。
    系统初始化时自动售货机中商品为6种商品,商品的单价参见1.1规格说明,存钱盒内放置1元、2元、5元、10元钱币,商品数量和钱币张数通过初始化命令设置,参见 2.1 系统初始化。

1.1、规格说明

1.1.1、商品:
  • 每种商品包含商品名称、单价、数量三种属性,其中商品名不重复。考生不能修改商品名称和单价,初始化命令设置商品数量。这些信息在考试框架中进行定义,考生在实现功能代码时可直接使用。
商品 名称单价数量
A12X
A23X
A34X
A45X
A58X
A66X
1.1.2、存钱盒信息
  • 钱币面额、张数两种属性。初始化命令设置各种面额钱币张数。这些信息在考试框架中进行定义,考生在实现功能代码时可直接使用。
钱币面额张数
10元X
5元X
2元X
1元X
1.1.3、退币原则
1.1.3.1、根据系统存钱盒内钱币的 信息 ,按钱币总张数最少的原则进行退币。
1.1.3.2、如果因零钱不足导致不能退币,则尽最大可能退币,以减少用户损失。
  • 例如:假设存钱盒内只有4张2元,无其它面额钱币。如果需要退币7元,系统因零钱不足无法退币,则继续尝试退币6元,最终系统成功退币3张2元,用户损失1元钱币。
1.1.4、投币操作说明
  • 每次投币成功,投入的钱币面额累加到投币余额;同时,本次投入的钱币放入存钱盒中,存钱盒相应面额钱币增加。
1.1.5、投币余额
  • 指当前自动售货机中用户剩余的可购买商品的钱币总额;例如:投入2元面额的钱币,投币余额增加2元;购买一件价格2元的商品,投币余额减少2元;
1.1.6、退币操作说明
  • 退币操作需要遵守 退币原则 ;退币成功后,投币余额清零,同时扣除存钱盒相应的金额。
1.1.7、购买商品操作说明
  • 一次仅允许购买一件商品;购买商品成功后,自动售货机中对应商品数量减1,投币余额扣除本次购买商品的价格。

2、操作说明

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

2.1 系统初始化

2.1.1、命令格式

r A1 数量 -A2 数量 -A3 数量 -A4 数量 -A5 数量 -A6 数量 1 元张数 -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]

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

2.1.2、功能说明

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

2.1.3、约束说明

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

2.1.4、输出说明

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

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

2.2、投币

2.2.1、命令格式

p 钱币面额

2.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”;

2.2.3、约束说明

(1) 系统在任意阶段都可以投币;
(2) 一次投币只能投一张钱币;
(3) 同等条件下,错误码的优先级:E002 > E003 > E005;

2.2.4、输出说明

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

命令输出
p 10;S002:Pay success,balance=10

2.3、购买商品

2.3.1、命令格式

b 商品名称

2.3.2、功能说明

(1) 如果购买的商品不在商品列表中,输出“E006:Goods does not exist”;
(2) 如果所购买的商品的数量为0,输出“E007:The goods sold out”;
(3) 如果投币余额小于待购买商品价格,输出“E008:Lack of balance”;
(4) 如果购买成功,输出“S003:Buy success,balance=X”;

2.3.3、约束说明

(1) 一次购买操作仅能购买一件商品,可以多次购买;
(2) 同等条件下,错误码的优先级:E006 > E007 > E008;

2.3.4、输出说明

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

命令输出
b A1;S003:Buy success,balance=8

2.4、退币

2.4.1、命令格式

c

2.4.2、功能说明

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

2.4.3、约束说明

(1) 系统在任意阶段都可以退币;
(2) 退币方式必须按照 退币原则 进行退币;

2.4.4、输出说明

如果退币成功,按照 退币原则 输出退币信息。
例,退5元钱币:

命令输出
c; 1 yuan coin number=0
2 yuan coin number=0
5 yuan coin number=1
10 yuan coin number=0

2.5、查询

2.5.1、命令格式

q 查询类别

2.5.2、功能说明

(1) 查询自动售货机中商品信息,包含商品名称、单价、数量。 根据商品数量从大到小进行排序;商品数量相同时,按照商品名称的先后顺序进行排序 。
例如:A1的商品名称先于A2的商品名称,A2的商品名称先于A3的商品名称。
(2) 查询存钱盒信息,包含各种面额钱币的张数;
(3) 查询类别如下表所示:

查询类别查询内容
0查询商品信息
1查询存钱盒信息
如果“查询类别”参数错误,输出“E010:Parameter error”。“查询类别”参数错误时,不进行下面的处理;
2.5.3、输出说明

“查询类别”为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

2、输入描述

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

3、输出描述

  • 输出执行结果

二、示例

2.1、示例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

三、答案(java)

3.1、方法一

package com.tzq.hwod;

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
	static ArrayList<Good> goods = new ArrayList<Good>();
	static ArrayList<Money> moneys = new ArrayList<Money>();
	static int goodTotal;
	static int moneyTotal;

	public static void main(String[] args) {
		goods.add(new Good("A1", 2));
		goods.add(new Good("A2", 3));
		goods.add(new Good("A3", 4));
		goods.add(new Good("A4", 5));
		goods.add(new Good("A5", 8));
		goods.add(new Good("A6", 6));

		moneys.add(new Money(1));
		moneys.add(new Money(2));
		moneys.add(new Money(5));
		moneys.add(new Money(10));
		Scanner sc = new Scanner(System.in);
		while (sc.hasNextLine()) {
			String str = sc.nextLine();
			String[] arr = str.split(";");
			for (int i = 0; i < arr.length; i++) {
				if (arr[i].contains("r")) {
					rStep(arr[i]);
				} else if (arr[i].contains("p")) {
					pStep(arr[i]);
				} else if (arr[i].contains("b")) {
					bStep(arr[i]);
				} else if (arr[i].contains("c")) {
					cStep(arr[i]);
				} else if (arr[i].contains("q")) {
					qStep(arr[i]);
				}
			}
		}

	}

	public static void rStep(String str) {
		String[] msg = str.split(" ");
		String[] goodNum = msg[1].split("-");
		for (int i = 0; i < goodNum.length; i++) {
			int count = Integer.parseInt(goodNum[i]);
			goods.get(i).count = count;
			goodTotal += count;
		}
		String[] moneyNum = msg[2].split("-");
		for (int i = 0; i < moneyNum.length; i++) {
			moneys.get(i).count = Integer.parseInt(moneyNum[i]);
		}
		moneyTotal = 0;// 每次初始化,投币余额必须赋0
		System.out.println("S001:Initialization is successful");
	}

	public static void pStep(String str) {
		String[] msg = str.split(" ");
		int num = Integer.parseInt(msg[1]);
		if (num != 1 && num != 2 && num != 5 && num != 10) {
			System.out.println("E002:Denomination error");
			return;
		}
		// 注意金额为2时需进行count*2才是金额总数
		if (num > 2 && moneys.get(0).count + moneys.get(1).count * 2 < num) {
			System.out.println("E003:Change is not enough, pay fail");
			return;
		}
		if (goodTotal == 0) {
			System.out.println("E005:All the goods sold out");
			return;
		}
		moneyTotal += num;
		// 注意,投入的金额需添加到对应的钱币盒内
		if (num == 1) {
			moneys.get(0).count += 1;
		} else if (num == 2) {
			moneys.get(1).count += 1;
		} else if (num == 5) {
			moneys.get(2).count += 1;
		} else if (num == 10) {
			moneys.get(3).count += 1;
		}
		System.out.println("S002:Pay success,balance=" + moneyTotal);
	}

	public static void bStep(String str) {
		String[] msg = str.split(" ");
		String name = msg[1];
		boolean existed = false;
		Good good = null;
		for (int i = 0; i < goods.size(); i++) {
			if (goods.get(i).name.equals(name)) {
				existed = true;
				good = goods.get(i);
				break;
			}
		}
		if (!existed) {
			System.out.println("E006:Goods does not exist");
			return;
		}
		if (goodTotal == 0) {
			System.out.println("E007:The goods sold out");
			return;
		}
		if (moneyTotal < good.price) {
			System.out.println("E008:Lack of balance");
			return;
		}
		moneyTotal -= good.price;
		System.out.println("S003:Buy success,balance=" + moneyTotal);
	}

	public static void cStep(String str) {
		if (moneyTotal == 0) {
			System.out.println("E009:Work failure");
			return;
		}
		int tenNum = 0;
		int fiveNum = 0;
		int secNum = 0;
		int oneNum = 0;
		while (moneyTotal >= 10 && moneys.get(3).count > 0) {
			moneyTotal -= 10;
			moneys.get(3).count -= 1;
			tenNum++;
		}
		while (moneyTotal >= 5 && moneys.get(2).count > 0) {
			moneyTotal -= 5;
			moneys.get(2).count -= 1;
			fiveNum++;
		}
		while (moneyTotal >= 2 && moneys.get(1).count > 0) {
			moneyTotal -= 2;
			moneys.get(1).count -= 1;
			secNum++;
		}
		while (moneyTotal >= 1 && moneys.get(0).count > 0) {
			moneyTotal -= 1;
			moneys.get(0).count -= 1;
			oneNum++;
		}
		moneyTotal = 0;
		System.out.println("1 yuan coin number=" + oneNum);
		System.out.println("2 yuan coin number=" + secNum);
		System.out.println("5 yuan coin number=" + fiveNum);
		System.out.println("10 yuan coin number=" + tenNum);
	}

	public static void qStep(String str) {
		// p0、p1需要判错
		if (!str.contains(" ")) {
			System.out.println("E010:Parameter error");
			return;
		}
		String[] arr = str.split(" ");
		int num = Integer.parseInt(arr[1]);
		if (num < 0 || num > 1) {
			System.out.println("E010:Parameter error");
			return;
		}
		if (num == 0) {
			Good good = null;
			for (int i = 0; i < goods.size(); i++) {
				good = goods.get(i);
				System.out.println(good.name + " " + good.price + " " + good.count);
			}
		} else {
			Money money = null;
			for (int i = 0; i < moneys.size(); i++) {
				money = moneys.get(i);
				System.out.println(money.id + " yuan coin number=" + money.count);
			}
		}
	}
}

class Good {
	String name;
	int price;
	int count;

	public Good(String name, int price) {
		this.name = name;
		this.price = price;
	}
}

class Money {
	int id;
	int count;

	public Money(int id) {
		this.id = id;
	}
}

在这里插入图片描述

四、答案(python 3)

4.1、方法一

这道题比较繁琐,花了些时间做出来了。思路就是用3个字典做记录‘价格、数量、零钱’。逐步写就行了。难点在于不要忘记操作后对‘数量、零钱’两个字典进行相应变更。找零部分比较搞笑根据题意分析,零钱内只有10元与1元的情况下,若找零7元则只找零1元,资本家永不吃亏.

#!/usr/bin/python
# -*- coding: UTF-8 -*-

def f(pq):
    w10, w5, w2, w1 = 0, 0, 0, 0  # 记录已经找出的零钱
    while pq > 0:  # 循环直到找零完成
        if pq >= 10 and dic_q['10'] >= 1:  # 可以找10元时
            pq -= 10  # 余额减10
            w10 += 1  # 已经找出的零钱+1
            dic_q['10'] -= 1  # 零钱10数量-1
        elif pq >= 5 and dic_q['5'] >= 1:  # 可以找5元时
            pq -= 5
            w5 += 1
            dic_q['5'] -= 1
        elif pq >= 2 and dic_q['2'] >= 1:
            pq -= 2
            w2 += 1
            dic_q['2'] -= 1
        elif pq >= 1 and dic_q['1'] >= 1:
            pq -= 1
            w1 += 1
            dic_q['1'] -= 1
        else:
            pq -= 1  # 耍赖,如果因零钱不足导致不能退币,则尽最大可能退币,以减少用户损失。
    return pq, w1, w2, w5, w10
while True:
    try:
        s = input().split(';')
        dic_m = {'A1': 2, 'A2': 3, 'A3': 4, 'A4': 5, 'A5': 8, 'A6': 6}  # 商品单价字典
        dic_n = {'A1': 0, 'A2': 0, 'A3': 0, 'A4': 0, 'A5': 0, 'A6': 0}  # 商品数量字典
        dic_q = {'10': 0, '5': 0, '2': 0, '1': 0}  # 零钱字典
        pq = 0
        for i in s[:-1]:
            if i[0] == 'r':  # 系统初始化,把商品数量和零钱放入字典
                b = i.split()
                m = b[1].split('-')
                q = b[2].split('-')
                dic_n['A1'], dic_n['A2'], dic_n['A3'], dic_n['A4'], dic_n['A5'], dic_n['A6'] = int(m[0]), int(m[1]), int(m[2]), int(m[3]), int(m[4]), int(m[5])
                dic_q['1'], dic_q['2'], dic_q['5'], dic_q['10'] = int(q[0]), int(q[1]), int(q[2]), int(q[3])
                print('S001:Initialization is successful')
            elif i[0] == 'p':  # 投币
                pq1 = int(i.split()[1])
                if pq1 not in [1, 2, 5, 10]:  # 币值非法
                    print('E002:Denomination error')
                elif pq1 not in [1, 2] and pq1 >= (dic_q['1'] + dic_q['2']*2):  # 存钱盒中1元和2元面额钱币总额小于本次投入的钱币面额
                    print('E003:Change is not enough, pay fail')
                elif dic_n['A1'] == 0 and dic_n['A2'] == 0 and dic_n['A3'] == 0 and dic_n['A4'] == 0 and dic_n['A5'] == 0 and dic_n['A6'] == 0:  # 自动售货机中商品全部销售完毕
                    print('E005:All the goods sold out')
                else :
                    dic_q[str(pq1)] += 1  # 字典对应币值零钱数量加一
                    pq += pq1  # 投币余额增加
                    print('S002:Pay success,balance={}'.format(pq))
            elif i[0] == 'b':  # 购买商品
                bn = i.split()[1]
                if bn not in dic_n.keys():  # 购买的商品不在商品列表中
                    print('E006:Goods does not exist')
                elif dic_n[bn] == 0:  # 所购买的商品的数量为0
                    print('E007:The goods sold out')
                elif int(pq) < dic_m[bn]:  # 投币余额小于待购买商品价格
                    print('E008:Lack of balance')
                else:
                    pq = int(pq) - dic_m[bn]  # 余额相应减少
                    print('S003:Buy success,balance={}'.format(pq))
                    dic_n[bn] -= 1  # 贩卖机物品数量减一
            elif i[0] == 'c':
                if pq == 0:  # 币余额等于0
                    print('E009:Work failure')
                else:  # 按照退币原则进行“找零”
                    pq, w1, w2, w5, w10= f(pq)  # f()函数实现过程
                    print('1 yuan coin number={}'.format(w1))
                    print('2 yuan coin number={}'.format(w2))
                    print('5 yuan coin number={}'.format(w5))
                    print('10 yuan coin number={}'.format(w10))
            elif i[0] == 'q':  # 查询功能
                if ' ' not in i:  # 给出的案例中q1之间无空格,非标准输入。为了过示例添加
                    print('E010:Parameter error')
                elif i.split()[1] not in ['0', '1']:  # “查询类别”参数错误
                    print('E010:Parameter error')
                elif i.split()[1] == '0':  # 查询类别0
                    print('A1 2 {}'.format(dic_n['A1']))
                    print('A2 3 {}'.format(dic_n['A2']))
                    print('A3 4 {}'.format(dic_n['A3']))
                    print('A4 5 {}'.format(dic_n['A4']))
                    print('A5 8 {}'.format(dic_n['A5']))
                    print('A6 6 {}'.format(dic_n['A6']))
                elif i.split()[1] == '1':  # 查询类别1
                    print('1 yuan coin number={}'.format(dic_q['1']))
                    print('2 yuan coin number={}'.format(dic_q['2']))
                    print('5 yuan coin number={}'.format(dic_q['5']))
                    print('10 yuan coin number={}'.format(dic_q['10']))
    except:
        break

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tzq@2018

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值