MediumClasses and objectsNot started

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
 C# · reference solution
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.

Your program
int count = int.Parse(Console.ReadLine()!);
var beds = new List<Bed>();
for (int i = 0; i < count; i++)
{
    string[] p = Console.ReadLine()!.Split(' ');
    // create the right kind of Bed from p and add it to beds
}

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();
}

// add Rect, Square and Circle classes that derive from Bed
Run is not available for C# in the browser yet. Write your program here, then download it and run it locally with .NET SDK 8.0 against the examples above. The reference solution below was verified the same way.

Tests: 5 cases including the examples. Passing every test marks the exercise solved in this browser.

How this page was checked. Every program on it was run with .NET SDK 8.0 at build time by the publishing checks, and the output shown is what it printed. Running C# inside the browser is not available yet, so the Run button is absent rather than pretending; copy the code and run it with .NET SDK 8.0 locally.