Garden bed areas
A landscaping planner describes garden beds by shape: a rectangle with a width and height, a square with one side, or a circle with a radius, all in metres. The planner needs the area of each bed and the total area to order soil.
Define an abstract class Bed with an abstract Area() method, one subclass per shape, and print every area followed by the total. Areas are printed with exactly two decimal places.
Input
The first line is an integer n. Each of the next n lines is one of rect w h, square s or circle r, with integer dimensions.
Output
n lines in input order, each kind area where kind is rect, square or circle and area has two decimals, then a final line Total area with the sum to two decimals.
Example 1
Input
3 rect 3 4 square 5 circle 2
Output
rect 12.00 square 25.00 circle 12.57 Total 49.57
3 x 4 = 12, 5 x 5 = 25, and pi x 2 x 2 = 12.566..., which rounds to 12.57. The total 49.566... rounds to 49.57.
Constraints
- 1 <= n <= 100
- 0 <= each dimension <= 1000
- Use Math.PI for circles
Hints
Hint 1 of 3
Each subclass stores its own dimensions in its constructor and overrides Area() with its own formula.
Hint 2 of 3
The first word of the line tells you which class to construct; a switch expression on p[0] reads cleanly.
Hint 3 of 3
Because every object is stored as a Bed, the printing loop calls bed.Area() without knowing which shape it is; the runtime picks the override.
Solution
Show a reference solution and explanation
int count = int.Parse(Console.ReadLine()!);
var beds = new List<Bed>();
for (int i = 0; i < count; i++)
{
string[] p = Console.ReadLine()!.Split(' ');
Bed bed = p[0] switch
{
"rect" => new Rect(int.Parse(p[1]), int.Parse(p[2])),
"square" => new Square(int.Parse(p[1])),
_ => new Circle(int.Parse(p[1]))
};
beds.Add(bed);
}
double total = 0;
foreach (Bed bed in beds)
{
Console.WriteLine($"{bed.Kind} {bed.Area():F2}");
total += bed.Area();
}
Console.WriteLine($"Total {total:F2}");
abstract class Bed
{
public abstract string Kind { get; }
public abstract double Area();
}
class Rect : Bed
{
private readonly int width;
private readonly int height;
public Rect(int width, int height) { this.width = width; this.height = height; }
public override string Kind => "rect";
public override double Area() => width * height;
}
class Square : Bed
{
private readonly int side;
public Square(int side) { this.side = side; }
public override string Kind => "square";
public override double Area() => side * side;
}
class Circle : Bed
{
private readonly int radius;
public Circle(int radius) { this.radius = radius; }
public override string Kind => "circle";
public override double Area() => Math.PI * radius * radius;
}
Why it works
This is polymorphism doing real work: the loop that prints and totals areas is written once against the abstract Bed type, and adding a fourth shape later would mean one new subclass and one more switch arm, with the loop untouched. An abstract method has no body in the base class, so the compiler refuses any subclass that forgets to override it. Math.PI * radius * radius is a double calculation while the rectangle and square areas are integer products silently widened to double on return. The F2 format specifier rounds to two decimals for display without altering the value used in the running total, which is why the total is computed from the unrounded areas.