Hone logo
Hone
Problems

Go Interfaces: Shape Calculator

Go's interfaces are a powerful mechanism for achieving polymorphism and decoupling. This challenge will test your understanding of how to define and implement interfaces in Go to create a flexible shape calculation system. You will need to define an interface that represents a generic shape and then implement this interface for different geometric shapes.

Problem Description

Your task is to create a system that can calculate the area and perimeter of various geometric shapes using Go interfaces. You will define an Shape interface that outlines the common behaviors expected of any shape (calculating area and perimeter). Then, you will implement this Shape interface for at least two different geometric shapes, such as a Circle and a Rectangle. Finally, you will write a function that accepts a slice of Shape interfaces and calculates the total area and perimeter of all shapes within that slice.

Key Requirements:

  1. Define a Shape Interface: This interface should have two methods:
    • Area() float64: Returns the area of the shape.
    • Perimeter() float64: Returns the perimeter of the shape.
  2. Implement Shape for Circle:
    • A Circle should be defined by its Radius (a float64).
    • Implement the Area() method for Circle using the formula: $\pi \times radius^2$.
    • Implement the Perimeter() method for Circle using the formula: $2 \times \pi \times radius$.
  3. Implement Shape for Rectangle:
    • A Rectangle should be defined by its Width and Height (both float64).
    • Implement the Area() method for Rectangle using the formula: $width \times height$.
    • Implement the Perimeter() method for Rectangle using the formula: $2 \times (width + height)$.
  4. Create a CalculateTotalMetrics Function: This function should:
    • Accept a slice of Shape interfaces ([]Shape).
    • Iterate through the slice, calling Area() and Perimeter() on each shape.
    • Return the sum of all areas and the sum of all perimeters as two float64 values.

Expected Behavior:

The system should correctly calculate the area and perimeter for each individual shape and aggregate them correctly when passed to the CalculateTotalMetrics function.

Edge Cases:

  • Shapes with zero dimensions (e.g., a circle with radius 0, a rectangle with width/height 0) should result in 0 area and 0 perimeter.
  • The input slice to CalculateTotalMetrics could be empty. In this case, the function should return 0 for both total area and total perimeter.

Examples

Example 1:

Input:
shapes := []Shape{
    Circle{Radius: 5.0},
    Rectangle{Width: 4.0, Height: 6.0},
}

Output:
Total Area: 103.53981633974483
Total Perimeter: 57.67944963603789

Explanation:

  • Circle Area: $\pi \times 5^2 = 78.53981633974483$
  • Circle Perimeter: $2 \times \pi \times 5 = 31.41592653589793$
  • Rectangle Area: $4 \times 6 = 24.0$
  • Rectangle Perimeter: $2 \times (4 + 6) = 20.0$
  • Total Area: $78.53981633974483 + 24.0 = 102.53981633974483$
  • Total Perimeter: $31.41592653589793 + 20.0 = 51.41592653589793$

Example 2:

Input:
shapes := []Shape{
    Circle{Radius: 0.0},
    Rectangle{Width: 10.0, Height: 0.0},
}

Output:
Total Area: 0.0
Total Perimeter: 20.0

Explanation:

  • Circle Area: $\pi \times 0^2 = 0.0$
  • Circle Perimeter: $2 \times \pi \times 0 = 0.0$
  • Rectangle Area: $10.0 \times 0.0 = 0.0$
  • Rectangle Perimeter: $2 \times (10.0 + 0.0) = 20.0$
  • Total Area: $0.0 + 0.0 = 0.0$
  • Total Perimeter: $0.0 + 20.0 = 20.0$

Example 3: (Empty Slice)

Input:
shapes := []Shape{}

Output:
Total Area: 0.0
Total Perimeter: 0.0

Explanation: An empty slice should result in zero total area and perimeter.

Constraints

  • All dimensions (Radius, Width, Height) will be non-negative float64 values.
  • The value of $\pi$ should be taken from the math package (math.Pi).
  • Performance is not a critical concern for this challenge; focus on correctness and idiomatic Go.

Notes

  • Remember that Go interfaces are satisfied implicitly. You don't need to explicitly declare that a type implements an interface.
  • Consider how you will represent $\pi$ in your calculations. The math package is your friend here.
  • Think about the return types of your Area and Perimeter methods. They should be float64 to handle potential decimal values.
  • You might want to create a main function to test your implementations with the example inputs.
Loading editor...
go