Здравствуйте, VladD2, Вы писали:
VD>Понимаю, что мышление человека инерно. По этому предлагаю начать с малого. Давай расширим оба примера поддержкой фунций с 3 и 5 параметрами. Причем на этот раз ты продемонстриуешь свое решение первым.
VD>Вторая здачка будет интереснее. Произвольная трансформация выражений. Берем исходное выражение применяем к нему некоторую функцию в параметах которой задем условия трасформации и получаем на выходе трансформированное (оптимизированное выражение). Для простоты, в качестве теста, будем использовать следующую оптимизацию — если выражение преставляет из себя "<любое выражение> * 1", то заменяем его на "<любое выражение>". Причем подразумевается, что это всего лишь один из возможных вариантов замены. Другими словами вызвав код вида:
VD>Теперь ход что называется за тобой. Ты представляешь свое решение, а затем я демонструю свое. Кстити, свое я уже написал .
Не мог вечером зайти в форум, какая-то ошибка, связанная с Dictionary Key, поэтому вечером писал по-памяти, что прочитал с утра, так что требования не соблюдены точно, но достаточно изоморфны.
150 строк, пока в c# не разочаровался.
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
abstract class Expression
{
public abstract double Eval();
public abstract override string ToString();
public abstract void RemoveOneParameterMin(ref Expression expression);
}
class Literal : Expression
{
double value;
public Literal(double value) { this.value = value; }
public override double Eval() { return value; }
public override string ToString() { return value.ToString(); }
public override void RemoveOneParameterMin(ref Expression expression) { }
}
abstract class Operation : Expression
{
protected Expression first, second;
public Expression First { get { return first; } }
public Expression Second { get { return second; } }
public Operation(Expression first, Expression second)
{
this.first = first;
this.second = second;
}
public override void RemoveOneParameterMin(ref Expression expression)
{
first.RemoveOneParameterMin(ref first);
second.RemoveOneParameterMin(ref second);
}
}
class Addition : Operation
{
public Addition(Expression first, Expression second) : base(first, second) { }
public override double Eval() { return first.Eval() + second.Eval(); }
public override string ToString() { return first.ToString() + " + " + second.ToString(); }
}
class Subtraction : Operation
{
public Subtraction(Expression first, Expression second) : base(first, second) { }
public override double Eval() { return first.Eval() - second.Eval(); }
public override string ToString() { return first.ToString() + " - " + second.ToString(); }
}
class Multiplication : Operation
{
public Multiplication(Expression first, Expression second) : base(first, second) { }
public override double Eval() { return first.Eval() * second.Eval(); }
public override string ToString() { return first.ToString() + " * " + second.ToString(); }
}
class Division : Operation
{
public Division(Expression first, Expression second) : base(first, second) { }
public override double Eval() { return first.Eval() / second.Eval(); }
public override string ToString() { return first.ToString() + " / " + second.ToString(); }
}
abstract class Call : Expression
{
protected Expression[] expressions;
public Expression[] Expressions { get { return expressions; } }
public Call(params Expression[] expressions) { this.expressions = expressions; }
protected string Join(string splitter)
{
if (expressions.Length == 0) return "";
StringBuilder stringBuilder = new StringBuilder();
foreach (Expression expression in expressions)
{
stringBuilder.Append(expression.ToString());
stringBuilder.Append(splitter);
}
return stringBuilder.Remove(stringBuilder.Length - splitter.Length, splitter.Length).ToString();
}
public override void RemoveOneParameterMin(ref Expression expression)
{
for (int index = 0; index < expressions.Length; index++ )
{
expression.RemoveOneParameterMin(ref expressions[index]);
}
}
}
abstract class AtLeastOneParameterCall : Call
{
public AtLeastOneParameterCall(Expression first, params Expression[] expressions) :
base(AtLeastOneParameterCall.Concat(first, expressions)) { }
private static Expression[] Concat(Expression first, params Expression[] expressions)
{
List<Expression> list = new List<Expression>(expressions);
list.Insert(0, first);
return list.ToArray();
}
protected delegate void CompareValues(double current, ref double value);
protected double FindValue(CompareValues compareValues)
{
double value = expressions[0].Eval();
for (int index = 1; index < expressions.Length; index++)
{
compareValues(expressions[index].Eval(), ref value);
}
return value;
}
}
class Min : AtLeastOneParameterCall
{
public Min(Expression first, params Expression[] expressions) : base(first, expressions) { }
public override string ToString() { return "Min(" + Join(", ") + ")"; }
public override double Eval() { return FindValue(ChooseMin); }
private void ChooseMin(double current, ref double value) { if (current < value) value = current; }
public override void RemoveOneParameterMin(ref Expression expression)
{
if (expressions.Length == 1)
{
expression = expressions[0];
}
else
{
base.RemoveOneParameterMin(ref expression);
}
}
}
class Max : AtLeastOneParameterCall
{
public Max(Expression first, params Expression[] expressions) : base(first, expressions) { }
public override string ToString() { return "Max(" + Join(", ") + ")"; }
public override double Eval() { return FindValue(ChooseMax); }
private void ChooseMax(double current, ref double value) { if (current > value) value = current; }
}
public class Program
{
public static void Main(string[] arguments)
{
// Min(1.23, 2.34 + Min(3.45))
Expression expression = new Min(new Literal(1.23), new Addition(new Literal(2.34), new Min(new Literal(3.45))));
Console.WriteLine("Expression '{0}' - {1}.", expression.ToString(), expression.Eval());
expression.RemoveOneParameterMin(ref expression);
Console.WriteLine("Expression '{0}' - {1}.", expression.ToString(), expression.Eval());
Console.ReadLine();
}
}