Chen Yu y Guo Yicai completaron esta operación por parejas.
Cero, dirección de github:
https://github.com/King-Authur/-Automatically-generate-four-arithmetic-problems
1. Requisitos relevantes del proyecto.
Implemente un programa de línea de comandos que genere automáticamente cuatro preguntas aritméticas de la escuela primaria (también puede usar una interfaz gráfica con funciones similares).
Requisitos del proyecto
- Utilice el parámetro -n para controlar el número de preguntas generadas, por ejemplo
Myapp.exe -n 10
Se generarán 10 preguntas.
- Use el parámetro -r para controlar el rango de valores numéricos (números naturales, fracciones verdaderas y denominadores de fracciones verdaderas) en la pregunta, por ejemplo
Myapp.exe -r 10
Se generarán cuatro problemas aritméticos dentro de 10 (excluyendo 10). Este parámetro se puede establecer en 1 u otros números naturales. Se debe proporcionar este parámetro; de lo contrario, el programa informa un error y proporciona información de ayuda.
-
En el problema generado, el proceso de cálculo no puede producir números negativos, es decir, si hay una subexpresión de la forma e1 − e2 en la expresión aritmética, entonces e1≥ e2.
-
Si hay una subexpresión de la forma e1 ÷ e2 en la pregunta generada, el resultado debería ser una fracción verdadera.
-
El número de operadores que aparecen en cada pregunta no excede de 3.
-
Las preguntas generadas por el programa en una ejecución no pueden repetirse, es decir, dos preguntas no pueden convertirse en la misma pregunta mediante un número limitado de intercambios de expresiones aritméticas + y ×.
Por ejemplo:
23 + 45 = y 45 + 23 = son preguntas repetidas
6 × 8 = y 8 × 6 = también son preguntas repetidas.
Las dos preguntas 3+ (2 + 1) y 1 + 2 + 3 son repetitivas, ya que + está asociado a la izquierda, 1 + 2 + 3 es equivalente a (1 + 2) +3, que es 3+ (1 +2), que es 3+ (2 + 1).
Pero 1 + 2 + 3 y 3 + 2 + 1 son dos preguntas que no se repiten, porque 1 + 2 + 3 es equivalente a (1 + 2) +3, y 3 + 2 + 1 es equivalente a (3 + 2 ) +1, no pueden convertirse en el mismo problema a través de un número limitado de intercambios.
Las preguntas generadas se almacenan en el archivo Exercises.txt en el directorio actual del programa de ejecución, en el siguiente formato:
1. Cuatro preguntas aritméticas 1
2. Cuatro preguntas aritméticas 2
......
Entre ellos, el puntaje verdadero está en el siguiente formato cuando se ingresa y sale: el puntaje verdadero de tres quintos se expresa como 3/5, y el puntaje verdadero de dos y octavos se expresa como 2'3 / 8.
- Mientras genera las preguntas, calcule las respuestas a todas las preguntas y guárdelas en el archivo Answers.txt en el directorio actual del programa en ejecución, en el siguiente formato:
1. Respuesta 1
2. Respuesta 2
En particular, el cálculo de la puntuación real se muestra en el siguiente ejemplo: 1/6 + 1/8 = 7/24.
-
El programa debería ser capaz de soportar la generación de 10,000 preguntas.
-
El programa admite el archivo de preguntas y el archivo de respuestas dados para determinar lo correcto y lo incorrecto en la respuesta y para contar el número. Los parámetros de entrada son los siguientes:
Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt
Los resultados estadísticos se envían al archivo Grade.txt en el siguiente formato:
Correcto: 5 (1, 3, 5, 7, 9)
Incorrecto: 5 (2, 4, 6, 8, 10)
El número 5 después de ":" indica el número de preguntas correctas / incorrectas, y el número de preguntas correctas / incorrectas está entre paréntesis. En aras de la simplicidad, se supone que las preguntas de entrada son todas preguntas numeradas que cumplen con las especificaciones.
Segundo, las dificultades encontradas y las soluciones.
(1) Cómo llevar a cabo la programación de pares
Antes de que comenzara el proyecto, tuvimos una discusión de más de una hora, aclaramos las ideas y llevamos a cabo el diseño general y la planificación del proyecto, y luego asignamos los módulos de los que fuimos responsables y escribimos Archivo de interfaz para desarrollo de proyectos.
En el proceso de programación, si encontramos dudas o sentimos que hay discrepancias en nuestras ideas, nos comunicaremos a WeChat a tiempo para asegurar el progreso normal del proyecto.
Después de completar la escritura del código, primero verificamos nuestro propio código y módulo de prueba, y luego integramos el código y lo enviamos a la otra parte para que la otra parte lo revise. En la operación real, hemos encontrado muchos errores entre nosotros.
(Dos)
3. Código clave y descripción del diseño
Diseño general
Definición de datos
typedef struct variable
{
int num_or_Symbol; //0是数字1是符号
int Symbol = -1; // + - * % ( ) 分别表示为 0 1 2 3 4 5
int numer; //如果是数字此为分子
int Den = 1; //如果是数字此为分母
int num;
bool operator == (variable c){
return num_or_Symbol == c.num_or_Symbol && Symbol == c.Symbol && numer == c.numer && Den == c.Den && num == c.num;
}
}var;
Las partes principales son las siguientes
//生成表达式函数
Status Create(var** exp, int size, int *length);
//计算表达式函数
Status Calculation(var* exp, int size, var* result, int length);
//中缀表达式转后缀表达式
Status Infix_to_Postfix(var* p, int size, var* Postfix, int length, int& postLen);
//判断两个问题是否等价
Status is_question_same(var* Question, int lenQuest, var* newQuestion, int lenNewQuest, int size);
//m指令的执行
void M_instructions(var** expression, int amount, int size, var* result);
//判断对错
void Correction(int* save, char* answerfile, char* exercisefile);
Código clave
Status Create(var** exp, int size, int* length)
{
var* expre;
int mark_num = random(1, 4);//计算符个数
int pre = 0;//前括号在第pre个数字前
int aft = 0;//后括号在第aft个数字后
int judge = 0;//判断,0写入数字,1写入符号
int n = 0;
*length = mark_num + mark_num + 1;
n = 0;
if (mark_num > 1)//如果运算符有3个,则存在括号
{
pre = random(1, mark_num);
if(pre == 1)//不让括号括住整个式子
aft = random((pre + 1), (mark_num + 1));
else
aft = random((pre + 1), (mark_num + 2));
(*length) += 2;
expre = new var[*length + 1];
expre[pre * 2 - 2].num_or_Symbol = 1;
expre[pre * 2 - 2].Symbol = 4;
expre[aft * 2].num_or_Symbol = 1;
expre[aft * 2].Symbol = 5;
}
else
{
expre = new var[*length + 1];
}
n = 0;
while (n < *length)
{
if (expre[n].Symbol < 4)
{
if (judge == 0)
{
expre[n].num_or_Symbol = 0;
expre[n].Den = random(2, size);
expre[n].numer = random(0, expre[n].Den);
expre[n].num = random(1, size);
judge = 1;
}
else
{
expre[n].num_or_Symbol = 1;
expre[n].Symbol = random(0, 4);
judge = 0;
}
}
n++;
}
*exp = expre;
return SUCCESS;
}
Status Infix_to_Postfix(var* p, int size, var* Postfix, int length, int& postLen)
{
//传入的postfix要记得为空
var stack[maxn];
int top = 0;
for (int i = 0; i < length; i++)
{
if (p[i].num_or_Symbol == 0)//是数字
{
Postfix[postLen++] = p[i];//放入输出串中
}
if (p[i].num_or_Symbol == 1 && p[i].Symbol == 4)//左括号
{
++top;
stack[top] = p[i];
}
while (p[i].num_or_Symbol == 1 && p[i].Symbol != 4 && p[i].Symbol != 5)
{
if (top == 0 || stack[top].Symbol == 4 || prio(p[i]) > prio(stack[top]))
{
++top;
stack[top] = p[i];
break;
}
else
{
Postfix[postLen++] = stack[top];
top--;
}
}
if (p[i].num_or_Symbol == 1 && p[i].Symbol == 5)//右括号
{
while (stack[top].Symbol != 4)
{
Postfix[postLen++] = stack[top];
top--;
}
top--;
}
}
while (top != 0)
{
Postfix[postLen++] = stack[top--];
}
return SUCCESS;
}
Status is_postfix_same(var* Question, int lenQuest, var* newQuestion, int lenNewQuest, int size)
{
var Postfix1[maxn], Postfix2[maxn];
var stack1[3][3], stack2[3][3];
int len1 = 0, len2 = 0, sta_size1 = 0, sta_size2 = 0;
//获取后缀表达式
Infix_to_Postfix(Question, size, Postfix1, lenQuest , len1);
Infix_to_Postfix(newQuestion, size, Postfix2, lenNewQuest, len2);
//获取子表达式
get_Subexpression(Postfix1, len1, stack1, sta_size1);
get_Subexpression(Postfix2, len2, stack2, sta_size2);
bool flag;
for (int i = 0; i < sta_size1; i++)
{
flag = false;
for (int j = 0; j < sta_size2; j++)
{
//短式等价
if (cmp(stack1[i], stack2[j]))
{
flag = true;
stack2[j][2].Symbol = -1;//将表达式的运算符删掉
break;
}
}
if (!flag)//如果存在不一样的,返回not same
{
return ERROR;
}
}
return SUCCESS;
}
void M_instructions(var **expression, int amount, int size, var* result)
{
fstream answer;
answer.open(ANSWERFILE, ios::out | ios::app);
var results[maxn];//后缀表达式
int length;
int i = 0;
int j = 0;
int k = 0;
while (i < amount)
{
Create(&expression[i], size, &length);
result[i].Symbol = length;
if (Calculation(expression[i], size, results, length) == ERROR || results[0].num >= size || results[0].numer >= size || results[0].Den >= size)
{
continue;
}
result[i].Den = results[0].Den;
result[i].num = results[0].num;
result[i].numer = results[0].numer;
result[i].num_or_Symbol = 0;
result[i].Symbol = length;
j = 0;
while (j < i)
{
//结果一样,表达式可能一样
if (result[j].Den == result[i].Den && result[j].numer == result[i].numer && result[j].num == result[i].num)
{
if (is_question_same(expression[i], result[i].Symbol, expression[j], result[j].Symbol, size))
{
break;
}
}
j++;
}
if (i != j)
{
if(k ++ < 20)//连续20次重复答案表明给的size太小,而amount太大,表达式多样性不足
continue;
}
Visit(expression[i], length, i + 1);
answer << i + 1 << ". ";
if (result[i].numer == 0)
{
answer << result[i].num;
}
else
{
if (result[i].num != 0)
{
answer << result[i].num;
answer << "`";
}
answer << result[i].numer;
answer << "/";
answer << result[i].Den;
}
answer << endl;
i++;
k = 0;
}
answer.close();
}
Cuatro, operación de prueba
Genera al azar 10 preguntas
Genere al azar 10 preguntas después de cambiar el valor de la pregunta
La prueba determina si es correcta o incorrecta después de completar la respuesta en el archivo exercisefile.txt
5. Formulario de PSP
PSP2.1 | Etapas del proceso de software personal | Tiempo estimado (minutos) | Tiempo real (minutos) |
---|---|---|---|
Planificación | Plan | 20 | 20 |
· Estimación | · Estime cuánto tiempo llevará esta tarea | 10 | 10 |
·Desarrollo | · Desarrollo | 120 | 100 |
· Análisis | · Análisis de necesidades (incluido el aprendizaje de nuevas tecnologías) | 60 60 | 60 60 |
· Especificaciones de diseño | · Generar documentos de diseño. | 20 | 20 |
· Revisión de diseño | · Revisión de diseño (revisión de documentos de diseño con colegas) | 10 | 10 |
· Estándar de codificación | · Especificaciones de código (haciendo especificaciones apropiadas para el desarrollo actual) | 5 5 | 10 |
· Diseño | · Diseño específico | 30 | 50 |
· Codificación | · Codificación específica | 180 | 200 |
· Revisión de código | · Revisión de código | 20 | 15 |
· Prueba | · Prueba (autocomprobación, modificar código, enviar cambios) | 20 | 20 |
Informes | Informe | 30 | 30 |
· Informe de prueba | · Informe de prueba | 20 | 15 |
· Medida del tamaño | · Calcular la carga de trabajo | 10 | 10 |
· Plan de mejora de procesos y autopsias | · Resumen luego, y proponer un plan de mejora de procesos | 30 | 30 |
Total | 585 | 600 |
6. Resumen del proyecto
Resumen de Guo Yicai:
1. En este proyecto, completamos cada tarea con mayor eficiencia a través de la programación de pares, el estímulo mutuo y la supervisión mutua. Reconocimos plenamente los beneficios de la programación de pares y entendimos su efectividad en la eficiencia de la programación y la verificación de errores. Gran efecto Por supuesto, también aprendí sus deficiencias , especialmente en el entorno objetivo de comunicación inconveniente durante la epidemia, la dificultad de comunicación también ha aumentado considerablemente, pero gracias a la función de pantalla compartida de la conferencia web, la conveniencia del teléfono WeChat, la comunicación del paciente con el paciente y la discusión activa y otros factores , Las deficiencias de la programación de pares también se han complementado enormemente.
2. En el curso del proyecto, aprendí cómo convertir expresiones de infijo en expresiones de sufijo, las reglas para calcular expresiones de sufijo y los métodos para determinar si las dos preguntas son equivalentes . También aprendí a escribir más estandarizado Interfaz de documentos, el recibo es bastante abundante.
3. Además, la interfaz gráfica todavía se está estudiando, y solo se puede hacer una interfaz simple, que no cumple con los requisitos de la parte de expansión del proyecto. Esto es un pequeño arrepentimiento. También es necesario inspirarse para aprender y dominar el conocimiento más rápido y mejor Para completar los requisitos del proyecto.
4. Finalmente, agradezco a mi compañero Chen Yu nuevamente.
Chen Yu Resumen:
1, este proyecto es la primera vez que trabajamos juntos para completar el proyecto por el método de programación de conexiones para la programación, y completar de manera muy eficiente los requisitos del proyecto , en el camino hubo muchos puntos de desacuerdo , pero a través de la programación en parejas Podemos debatir y unificar nuestras opiniones de manera oportuna, para que no se pierda demasiado tiempo en lugares innecesarios .
2. Originalmente, quería que el usuario completara la respuesta en el programa, pero debido a que no pensé en una mejor forma interactiva, al final no implementé esta función, y solo dejé que el usuario completara la respuesta manualmente en el archivo txt.
3. Finalmente, ¡es realmente cómodo trabajar con el líder de Yicai! !