华为OD机试 - 仿LISP运算(Python/JS/C/C++ 2025 B卷 200分)

在这里插入图片描述

2025B卷华为OD机试统一考试题库清单(持续收录中)以及考点说明(Python/JS/C/C++)

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

一、题目描述

LISP语言唯一的语法就是括号要配对,形如(OP P1 P2 …),括号内元素由单个空格分割。其中第一个元素OP为操作符,后续元素均为其参数,参数个数取决于操作符类型。

注意:参数P1,P2也有可能是另外一个嵌套的(OP P1 P2…),当前OP类型为add/sub/mul/div(全小写) 分别代表整数的加减乘除法,简单起见,所有OP参数个数均为2。

举例:

输入输出
(mul 3 -7)-21
(add 1 2)3
(sub (mul 2 4) (div 9 3))5

二、输入描述

输入为长度不超过512的字符串,用例保证了无语法错误

三、输出描述

输出计算结果或者“error”。

四、测试用例

测试用例1

1、输入

(mul (sub 10 2) (add 1 2))

2、输出

24

3、说明

计算过程为 (10-2) * (1+2) = 8 * 3 = 24

测试用例2

1、输入

(div 10 0)

2、输出

error

3、说明

除数为0,抛出错误

五、解题思路

  1. 去除外层括号
  2. 提取操作符
  3. 解析两个参数(考虑嵌套括号)
  4. 递归计算参数值
  5. 根据操作符执行运算
  6. 处理除零异常

六、Python算法源码

# Python实现
def calculate(expr):
    """主计算函数"""
    try:
        result = evaluate(expr)
        return str(result)
    except Exception:
        return "error"

def evaluate(expr):
    """递归求值函数"""
    expr = expr.strip()
    
    # 如果是纯数字,直接返回
    if not expr.startswith("("):
        return int(expr)
    
    # 去掉外层括号
    expr = expr[1:-1]
    
    # 找到操作符
    first_space = expr.find(' ')
    op = expr[:first_space]
    rest = expr[first_space + 1:]
    
    # 解析两个参数
    params = parse_params(rest)
    param1 = evaluate(params[0])
    param2 = evaluate(params[1])
    
    # 根据操作符计算结果
    if op == "add":
        return param1 + param2
    elif op == "sub":
        return param1 - param2
    elif op == "mul":
        return param1 * param2
    elif op == "div":
        if param2 == 0:
            raise ArithmeticError("除零错误")
        return param1 // param2  # 整数除法
    else:
        raise ValueError(f"未知操作符: {op}")

def parse_params(rest):
    """解析参数,返回两个参数的列表"""
    params = ["", ""]
    level = 0
    start = 0
    param_index = 0
    
    # 遍历字符串,根据括号层级分割参数
    for i, c in enumerate(rest):
        if c == '(':
            level += 1
        elif c == ')':
            level -= 1
        elif c == ' ' and level == 0:
            # 当括号层级为0时,空格是参数分隔符
            params[param_index] = rest[start:i]
            param_index += 1
            start = i + 1
            if param_index == 2:
                break
    
    # 最后一个参数
    if param_index < 2:
        params[param_index] = rest[start:]
    
    return params

# 主函数
if __name__ == "__main__":
    expr = input()
    print(calculate(expr))

七、JavaScript算法源码

// JavaScript实现
const readline = require('readline');

// 创建读取接口
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 主计算函数
function calculate(expr) {
    try {
        const result = evaluate(expr);
        return String(result);
    } catch (e) {
        return "error";
    }
}

// 递归求值函数
function evaluate(expr) {
    expr = expr.trim();
    
    // 如果是纯数字,直接返回
    if (!expr.startsWith("(")) {
        return parseInt(expr);
    }
    
    // 去掉外层括号
    expr = expr.substring(1, expr.length - 1);
    
    // 找到操作符
    const firstSpace = expr.indexOf(' ');
    const op = expr.substring(0, firstSpace);
    const rest = expr.substring(firstSpace + 1);
    
    // 解析两个参数
    const params = parseParams(rest);
    const param1 = evaluate(params[0]);
    const param2 = evaluate(params[1]);
    
    // 根据操作符计算结果
    switch (op) {
        case "add":
            return param1 + param2;
        case "sub":
            return param1 - param2;
        case "mul":
            return param1 * param2;
        case "div":
            if (param2 === 0) {
                throw new Error("除零错误");
            }
            return Math.floor(param1 / param2);  // 整数除法
        default:
            throw new Error("未知操作符: " + op);
    }
}

// 解析参数,返回两个参数的数组
function parseParams(rest) {
    const params = ["", ""];
    let level = 0;
    let start = 0;
    let paramIndex = 0;
    
    // 遍历字符串,根据括号层级分割参数
    for (let i = 0; i < rest.length; i++) {
        const c = rest.charAt(i);
        if (c === '(') {
            level++;
        } else if (c === ')') {
            level--;
        } else if (c === ' ' && level === 0) {
            // 当括号层级为0时,空格是参数分隔符
            params[paramIndex++] = rest.substring(start, i);
            start = i + 1;
            if (paramIndex === 2) {
                break;
            }
        }
    }
    
    // 最后一个参数
    if (paramIndex < 2) {
        params[paramIndex] = rest.substring(start);
    }
    
    return params;
}

// 读取输入并处理
rl.on('line', (input) => {
    console.log(calculate(input));
    rl.close();
});

八、C算法源码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 函数声明
char* calculate(char* expr);
int evaluate(char* expr);
void parseParams(char* rest, char params[2][256]);
char* trim(char* str);
int findMatchingParen(char* str, int start);

// 主函数
int main() {
    char input[512];
    fgets(input, sizeof(input), stdin);
    
    // 移除换行符
    input[strcspn(input, "\n")] = 0;
    
    // 计算结果
    char* result = calculate(input);
    printf("%s\n", result);
    
    return 0;
}

// 主计算函数
char* calculate(char* expr) {
    static char result[20];
    
    // 尝试计算
    int value = evaluate(expr);
    
    // 如果返回值是特殊值-999999,表示错误
    if (value == -999999) {
        strcpy(result, "error");
    } else {
        sprintf(result, "%d", value);
    }
    
    return result;
}

// 递归求值函数
int evaluate(char* expr) {
    expr = trim(expr);
    
    // 如果是纯数字,直接返回
    if (expr[0] != '(') {
        return atoi(expr);
    }
    
    // 复制表达式以便修改
    char temp[512];
    strcpy(temp, expr);
    
    // 去掉外层括号
    int len = strlen(temp);
    temp[len - 1] = '\0';
    char* inner = temp + 1;
    
    // 找到操作符
    char* space = strchr(inner, ' ');
    if (!space) return -999999;
    
    *space = '\0';
    char* op = inner;
    char* rest = space + 1;
    
    // 解析两个参数
    char params[2][256];
    parseParams(rest, params);
    
    // 递归计算参数值
    int param1 = evaluate(params[0]);
    int param2 = evaluate(params[1]);
    
    // 检查错误
    if (param1 == -999999 || param2 == -999999) {
        return -999999;
    }
    
    // 根据操作符计算结果
    if (strcmp(op, "add") == 0) {
        return param1 + param2;
    } else if (strcmp(op, "sub") == 0) {
        return param1 - param2;
    } else if (strcmp(op, "mul") == 0) {
        return param1 * param2;
    } else if (strcmp(op, "div") == 0) {
        if (param2 == 0) {
            return -999999;  // 除零错误
        }
        return param1 / param2;
    } else {
        return -999999;  // 未知操作符
    }
}

// 解析参数,分割成两个参数
void parseParams(char* rest, char params[2][256]) {
    int level = 0;
    int start = 0;
    int paramIndex = 0;
    int len = strlen(rest);
    
    // 遍历字符串,根据括号层级分割参数
    for (int i = 0; i < len; i++) {
        char c = rest[i];
        if (c == '(') {
            level++;
        } else if (c == ')') {
            level--;
        } else if (c == ' ' && level == 0) {
            // 当括号层级为0时,空格是参数分隔符
            strncpy(params[paramIndex], rest + start, i - start);
            params[paramIndex][i - start] = '\0';
            paramIndex++;
            start = i + 1;
            if (paramIndex == 2) {
                break;
            }
        }
    }
    
    // 最后一个参数
    if (paramIndex < 2) {
        strcpy(params[paramIndex], rest + start);
    }
}

// 去除字符串两端的空格
char* trim(char* str) {
    // 去除开头空格
    while (*str == ' ') str++;
    
    // 去除结尾空格
    int len = strlen(str);
    while (len > 0 && str[len - 1] == ' ') {
        str[--len] = '\0';
    }
    
    return str;
}

九、C++算法源码

#include <iostream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

// 函数声明
string calculate(const string& expr);
int evaluate(const string& expr);
vector<string> parseParams(const string& rest);
string trim(const string& str);

// 主函数
int main() {
    string input;
    getline(cin, input);
    
    // 计算结果
    string result = calculate(input);
    cout << result << endl;
    
    return 0;
}

// 主计算函数
string calculate(const string& expr) {
    try {
        int result = evaluate(expr);
        return to_string(result);
    } catch (...) {
        return "error";
    }
}

// 递归求值函数  
int evaluate(const string& expr) {
    string trimmedExpr = trim(expr);
    
    // 如果是纯数字,直接返回
    if (trimmedExpr[0] != '(') {
        return stoi(trimmedExpr);
    }
    
    // 去掉外层括号
    string inner = trimmedExpr.substr(1, trimmedExpr.length() - 2);
    
    // 找到操作符
    size_t firstSpace = inner.find(' ');
    if (firstSpace == string::npos) {
        throw runtime_error("无效表达式");
    }
    
    string op = inner.substr(0, firstSpace);
    string rest = inner.substr(firstSpace + 1);
    
    // 解析两个参数
    vector<string> params = parseParams(rest);
    int param1 = evaluate(params[0]);
    int param2 = evaluate(params[1]);
    
    // 根据操作符计算结果
    if (op == "add") {
        return param1 + param2;
    } else if (op == "sub") {
        return param1 - param2;
    } else if (op == "mul") {
        return param1 * param2;
    } else if (op == "div") {
        if (param2 == 0) {
            throw runtime_error("除零错误");
        }
        return param1 / param2;
    } else {
        throw runtime_error("未知操作符");
    }
}

// 解析参数,返回两个参数的向量
vector<string> parseParams(const string& rest) {
    vector<string> params;
    int level = 0;
    size_t start = 0;
    
    // 遍历字符串,根据括号层级分割参数
    for (size_t i = 0; i < rest.length(); i++) {
        char c = rest[i];
        if (c == '(') {
            level++;
        } else if (c == ')') {
            level--;
        } else if (c == ' ' && level == 0) {
            // 当括号层级为0时,空格是参数分隔符
            params.push_back(rest.substr(start, i - start));
            start = i + 1;
            if (params.size() == 2) {
                break;
            }
        }
    }
    
    // 最后一个参数
    if (params.size() < 2) {
        params.push_back(rest.substr(start));
    }
    
    return params;
}

// 去除字符串两端的空格
string trim(const string& str) {
    size_t first = str.find_first_not_of(' ');
    if (first == string::npos) {
        return "";
    }
    size_t last = str.find_last_not_of(' ');
    return str.substr(first, last - first + 1);
}

🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2025 B卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

哪 吒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值