仿LISP运算

仿LISP运算

真题目录: 点击去查看

E 卷 200分题型

题目描述

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
  • 输入:(div 1 0) 输出:error

题目涉及数字均为整数,可能为负;

不考虑 32 位溢出翻转,计算过程中也不会发生 32 位溢出翻转,

除零错误时,输出 “error”,

除法遇除不尽,向下取整,即 3/2 = 1

输入描述

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

输出描述

输出计算结果或者“error”

用例1

输入

(div 12 (sub 45 45))

输出

error

说明

45减45得0,12除以0为除零错误,输出error

用例2

输入

(add 1 (div -7 3))

输出

-2

说明

-7除以3向下取整得-3,1加-3得-2

题解

思路:

纯逻辑题,难点在于将括号中的片段截取出来,我的处理方案是,遍历输入的每一个字符,当遇到")“时,则在其前面必然存在一个“(”,找到其前面第一个“(”,然后截取“(”和”)"之间的内容(从栈中截取走),进行计算,将结果回填如栈中。

c++

#include <iostream>
#include <stack>
#include <vector>
#include <sstream>
#include <cmath>

using namespace std;

int operate(const string& op, int p1, int p2) {
    if (op == "add") return p1 + p2;
    if (op == "sub") return p1 - p2;
    if (op == "mul") return p1 * p2;
    if (op == "div") {
        if (p2 == 0) throw runtime_error("error");
        return floor(1.0 * p1 / p2);  // 向下取整
    }
    throw runtime_error("error");
}

string getResult(const string& s) {
    // 记录一个括号开始之前栈中元素个数
    stack<int> leftIdx;
    // 存储运算符和运算数字
    vector<string> stack;
    
    for (size_t i = 0; i < s.length(); ++i) {
        if (s[i] == ')') {
            int l = leftIdx.top();
            leftIdx.pop();
            
            vector<string> fragment(stack.begin() + l, stack.end());
            stack.erase(stack.begin() + l, stack.end());
            
            if (fragment.size() != 3) return "error";
            
            try {
                int p1 = stoi(fragment[1]);
                int p2 = stoi(fragment[2]);
                int res = operate(fragment[0], p1, p2);
                stack.push_back(to_string(res));
            } catch (...) {
                return "error";
            }
        } else if (s[i] == '(') {
            leftIdx.push(stack.size());
        } else if (s[i] != ' ') {
            string token;
            while (i < s.length() && s[i] != ' ' && s[i] != ')') {
                token += s[i];
                ++i;
            }
            --i;
            stack.push_back(token);
        }
    }
    return stack.empty() ? "error" : stack[0];
}

int main() {
    string s;
    getline(cin, s);
    try {
        cout << getResult(s) << endl;
    } catch (const exception& e) {
        cout << "error" << endl;
    }
    return 0;
}

JAVA

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.println(getResult(sc.nextLine()));
  }

  public static String getResult(String s) {
    LinkedList<Character> stack = new LinkedList<>();
    LinkedList<Integer> leftIdx = new LinkedList<>();

    for (int i = 0; i < s.length(); i++) {
      char c = s.charAt(i);

      if (c == ')') {
        List<Character> fragment = stack.subList(leftIdx.removeLast(), stack.size());

        StringBuilder sb = new StringBuilder();
        for (int j = 1; j < fragment.size(); j++) sb.append(fragment.get(j));

        fragment.clear();

        String[] tmp = sb.toString().split(" ");

        String op = tmp[0];
        int p1 = Integer.parseInt(tmp[1]);
        int p2 = Integer.parseInt(tmp[2]);

        String res = operate(op, p1, p2);
        if ("error".equals(res)) {
          return "error";
        } else {
          for (int k = 0; k < res.length(); k++) stack.add(res.charAt(k));
        }
      } else if (c == '(') {
        leftIdx.add(stack.size());
        stack.add(c);
      } else {
        stack.add(c);
      }
    }

    StringBuilder ans = new StringBuilder();
    for (Character c : stack) ans.append(c);
    return ans.toString();
  }

  public static String operate(String op, int p1, int p2) {
    switch (op) {
      case "add":
        return p1 + p2 + "";
      case "sub":
        return p1 - p2 + "";
      case "mul":
        return p1 * p2 + "";
      case "div":
        return p2 == 0 ? "error" : (int) Math.floor(p1 / (p2 + 0.0)) + "";
      default:
        return "error";
    }
  }
}

Python

import math

# 输入获取
s = input()


def operate(op, p1, p2):
    p1 = int(p1)
    p2 = int(p2)
    if op == "add":
        return str(p1 + p2)
    elif op == "sub":
        return str(p1 - p2)
    elif op == "mul":
        return str(p1 * p2)
    elif op == "div":
        if p2 == 0:
            return "error"
        else:
            return str(int(math.floor(p1 / p2)))
    else:
        return "error"


# 算法入口
def getResult():
    stack = []
    leftIdx = []

    for i in range(len(s)):
        if s[i] == ')':
            l = leftIdx.pop()
            fragment = stack[l:]
            del stack[l:]

            op, p1, p2 = "".join(fragment[1:]).split(" ")

            res = operate(op, p1, p2)

            if res == "error":
                return "error"
            else:
                stack.extend(list(res))
        elif s[i] == '(':
            leftIdx.append(len(stack))
            stack.append(s[i])
        else:
            stack.append(s[i])

    return "".join(stack)


# 调用算法
print(getResult())

JavaScript

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

rl.on("line", (line) => {
  console.log(getResult(line));
});

function getResult(s) {
  const stack = [];
  const leftIdx = [];

  for (let i = 0; i < s.length; i++) {
    if (s[i] === ")") {
      const fragment = stack.splice(leftIdx.pop());

      const [op, p1, p2] = fragment.slice(1).join("").split(" ");
      const res = operate(op, p1 - 0, p2 - 0);

      if (res === "error") return "error";
      else stack.push(...String(res));
    } else if (s[i] === "(") {
      leftIdx.push(stack.length);
      stack.push(s[i]);
    } else {
      stack.push(s[i]);
    }
  }

  return stack.join("");
}

function operate(op, p1, p2) {
  switch (op) {
    case "add":
      return p1 + p2;
    case "sub":
      return p1 - p2;
    case "mul":
      return p1 * p2;
    case "div":
      return p2 === 0 ? "error" : Math.floor(p1 / p2);
  }
}

Go

package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
)

// operate 计算加、减、乘、除运算
func operate(op string, p1, p2 int) (int, error) {
	switch op {
	case "add":
		return p1 + p2, nil
	case "sub":
		return p1 - p2, nil
	case "mul":
		return p1 * p2, nil
	case "div":
		if p2 == 0 {
			return 0, fmt.Errorf("error") // 返回错误
		}
		return int(math.Floor(float64(p1) / float64(p2))), nil
	default:
		return 0, fmt.Errorf("error") // 无效运算符
	}
}

// getResult 解析 LISP 表达式并计算结果
func getResult(s string) string {
	var stack []string
	var leftIdx []int // 记录 '(' 在 stack 中的索引

	for i := 0; i < len(s); i++ {
		if s[i] == ')' {
			// 取出最近的 '(' 位置
			if len(leftIdx) == 0 {
				return "error"
			}
			l := leftIdx[len(leftIdx)-1]
			leftIdx = leftIdx[:len(leftIdx)-1]

			// 取出括号内的内容
			fragment := stack[l:]
			stack = stack[:l] // 移除括号内的内容

			if len(fragment) != 3 {
				return "error"
			}

			// 解析操作符和两个操作数
			p1, err1 := strconv.Atoi(fragment[1])
			p2, err2 := strconv.Atoi(fragment[2])
			if err1 != nil || err2 != nil {
				return "error"
			}

			// 执行计算
			res, err := operate(fragment[0], p1, p2)
			if err != nil {
				return "error"
			}

			// 结果存入 stack
			stack = append(stack, strconv.Itoa(res))
		} else if s[i] == '(' {
			leftIdx = append(leftIdx, len(stack))
		} else if s[i] != ' ' {
			// 读取完整的 token
			token := ""
			for i < len(s) && s[i] != ' ' && s[i] != ')' {
				token += string(s[i])
				i++
			}
			i-- // 回退一格防止跳过字符
			stack = append(stack, token)
		}
	}

	if len(stack) != 1 {
		return "error"
	}
	return stack[0]
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	if scanner.Scan() {
		expr := scanner.Text()
		fmt.Println(getResult(expr))
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/965316.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在线教程丨YOLO系列10年更新11个版本,最新模型在目标检测多项任务中达SOTA

YOLO (You Only Look Once) 是计算机视觉领域中最具影响力的实时目标检测算法之一&#xff0c;以其高精度与高效性深受业界青睐&#xff0c;广泛应用于自动驾驶、安防监控、医疗影像等领域。 该模型最早于 2015 年由华盛顿大学研究生 Joseph Redmon 发布&#xff0c;开创了将目…

面向对象程序设计-实验1

6-1 求两个或三个整数中的最大数&#xff0c;用带默认参数的函数实现 本题要求实现一个带默认参数的函数&#xff0c;求两个或三个整数中的最大数 代码清单&#xff1a; #include <iostream> using namespace std; int main() { int max( int a,int b,int c0); int …

如何打开vscode系统用户全局配置的settings.json

&#x1f4cc; settings.json 的作用 settings.json 是 Visual Studio Code&#xff08;VS Code&#xff09; 的用户配置文件&#xff0c;它存储了 编辑器的个性化设置&#xff0c;包括界面布局、代码格式化、扩展插件、快捷键等&#xff0c;是用户全局配置&#xff08;影响所有…

2025简约的打赏系统PHP网站源码

源码介绍 2025简约的打赏系统PHP网站源码 源码上传服务器&#xff0c;访问域名/install.php安装 支持自定义金额打赏 集成支付宝当面付 后台管理系统 订单记录查询 效果预览 源码获取 2025简约的打赏系统PHP网站源码

自指学习:AGI的元认知突破

文章目录 引言:从模式识别到认知革命一、自指学习的理论框架1.1 自指系统的数学定义1.2 认知架构的三重反射1.3 与传统元学习的本质区别二、元认知突破的技术路径2.1 自指神经网络架构2.2 认知效能评价体系2.3 知识表示的革命三、实现突破的关键挑战3.1 认知闭环的稳定性3.2 计…

Ubutun本地部署DeepSeek R1

目录 一、本地部署&终端命令行交互 二、网页端交互 三、参考链接 一、本地部署&终端命令行交互 Ollama 是一个轻量级的大语言模型管理工具&#xff0c;支持 Windows / Mac / Linux。 Ollama官网&#xff1a;Ollama # 下载安装ollama curl -fsSL https://ollama.co…

【Linux】Linux经典面试题

文章目录 1. Linux文件系统1.1 什么是inode&#xff1f;1.2 硬链接和软链接的区别1.3 文件权限和所有权 2. Linux进程管理2.1 进程和线程的区别2.2 进程间通信&#xff08;IPC&#xff09;2.3 守护进程&#xff08;Daemon&#xff09; 3. Linux内存管理3.1 虚拟内存和物理内存3…

MySQL 缓存机制与架构解析

目录 一、MySQL缓存机制概述 二、MySQL整体架构 三、SQL查询执行全流程 四、MySQL 8.0为何移除查询缓存&#xff1f; 五、MySQL 8.0前的查询缓存配置 六、替代方案&#xff1a;应用层缓存与优化建议 总结 一、MySQL缓存机制概述 MySQL的缓存机制旨在提升数据访问效率&am…

递归练习八(记忆化搜索)

一、解题心得 记忆化搜索就是带着备忘录递归搜索。 函数体设计&#xff1a;进 dfs 后先看看要找的值是不是在备忘录里面存着&#xff0c;有就直接返回&#xff0c;没有再考虑递归出口和中间函数逻辑。 记忆化搜索和递归暴搜都没有很大的关系&#xff0c;而是和动态规划问题有…

uniapp小程序自定义中间凸起样式底部tabbar

我自己写的自定义的tabbar效果图 废话少说咱们直接上代码&#xff0c;一步一步来 第一步&#xff1a; 找到根目录下的 pages.json 文件&#xff0c;在 tabBar 中把 custom 设置为 true&#xff0c;默认值是 false。list 中设置自定义的相关信息&#xff0c; pagePath&#x…

app专项测试(网络测试流程)

一、网络测试的一般流程 step1&#xff1a;首先要考虑网络正常的情况 ① 各个模块的功能正常可用 ② 页面元素/数据显示正常 step2&#xff1a;其次要考虑无网络的情况 ① APP各个功能在无网络情况下是否可用 ② APP各个页面之间切换是否正常 ③ 发送网络请求时是…

【Kubernetes Pod间通信-第3篇】Kubernetes中Pod与ClusterIP服务之间的通信

引言 我们之前了解了在不同场景下,Kubernetes中Pod之间的通信是如何路由的。 【Kubernetes Pod间通信-第1篇】在单个子网中使用underlay网络实现Pod到Pod的通信【Kubernetes Pod间通信-第2篇】使用BGP实现Pod到Pod的通信现在,我们来看看在集群中,Pod与服务之间的通信是如何…

【免费】2007-2019年各省科技支出占一般公共预算支出的比重数据

2007-2019年各省科技支出占一般公共预算支出的比重数据 1、时间&#xff1a;2007-2019年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;行政区划代码、地区名称、年份、科技支出占一般公共预算支出的比重 4、范围&#xff1a;31省 5、指标解释&#xff1a…

【LeetCode】day15 142.环形链表II

142. 环形链表 II - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则…

C基础(六)指针,指针的基础概念、变量定义、运算、大小等

指针&#xff1a; 什么是指针&#xff1a;指针表示内存地址&#xff0c;平时所说的指针一般是保存地址的指针变量。定义指针变量 格式&#xff1a;数据类型 *指针变量名。初始化和赋值&#xff1a;指针指向变量的首地址。定义指针后若未赋值则为野指针&#xff1b;可将变量地址…

【R语言】获取数据

R语言自带2种数据存储格式&#xff1a;*.RData和*.rds。 这两者的区别是&#xff1a;前者既可以存储数据&#xff0c;也可以存储当前工作空间中的所有变量&#xff0c;属于非标准化存储&#xff1b;后者仅用于存储单个R对象&#xff0c;且存储时可以创建标准化档案&#xff0c…

央行发布《贸易金融分布式账本技术要求》,参考架构包括5部分

《银行科技研究社》(作者 木子剑):2024年12月11日,中国人民银行发布金融行业标准《贸易金融分布式账本技术要求》(JR/T 0308-2024)(以下简称“《要求》”),当日实施。据悉,该文件的起草单位包括6大行和多家股份制银行等。 《要求》规定了分布式账本技术在贸易金融领域…

CSS盒模型详解:从零开始理解margin、border、padding

引言 在CSS中&#xff0c;盒模型(Box Model)是一个非常基础且重要的概念。它定义了网页中每个元素如何占据空间以及元素间的关系。今天&#xff0c;我们就通过简单的例子来理解盒模型的构成。 盒模型的组成部分 CSS盒模型主要由四个部分组成&#xff08;从外到内&#xff09…

DS图(中)(19)

文章目录 前言一、图的遍历广度优先遍历深度优先遍历 二、最小生成树Kruskal算法Prim算法两种方法对比 总结 前言 承上启下&#xff0c;我们来学习下图的中篇&#xff01;&#xff01;&#xff01; 一、图的遍历 图的遍历指的是遍历图中的顶点&#xff0c;主要有 广度优先遍历 …

112,【4】攻防世界 web weak_auth

之前做过&#xff0c;回顾 进入靶场 输入admin 123456 不是&#xff0c;这也行&#xff0c;什么闭合方式&#xff0c;注释符都没用上 反而不自然了 不过输入admin 123456 纯属个人习惯 假如我没那么输&#xff0c;或者用户名&#xff0c;密码不是这两个&#xff0c;我该怎…