Created
December 22, 2014 19:40
-
-
Save blakemerryman/a45416b6d751fa5b9f68 to your computer and use it in GitHub Desktop.
DailyProgrammer-Challenge193_ContainerDimensions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env xcrun swift | |
/* | |
/r/DailyProgrammer Challenge # 193 | |
Reddit - http://www.reddit.com/r/dailyprogrammer/ | |
Blake Merryman | |
Github - https://github.com/blakemerryman | |
Challenge Description: | |
An international shipping company is trying to figure out how to manufacture various types of containers. Given a volume they want to figure out the dimensions of various shapes that would all hold the same volume. | |
Input: | |
* A volume in cubic meters. | |
Output: | |
* Dimensions of containers of various types that would hold the volume. | |
* The following containers are possible. | |
* Cube | |
* Ball (Sphere) | |
* Cylinder | |
* Cone | |
Ex: | |
Input: | |
> 27.0 | |
Output: | |
> Cube: 3.00m width, 3.00m high, 3.00m tall | |
Cylinder: 3.00m tall, Diameter of 3.38m | |
Sphere: 1.86m Radius | |
Cone: 9.00m tall, 1.69m Radius | |
Notes: | |
* Input can be an integer or double value | |
* To run, | |
1. Make executable (chmod +x filename.swift) | |
2. Run by entering the following into the console: | |
> ./filename.swift ### | |
or | |
> ./filename.swift ###.## | |
*/ | |
import Cocoa | |
// MARK: - Handle User Input | |
var volume = 0.0 | |
// Grab input from console | |
for argument in Process.arguments { | |
let argumentAsDouble = (argument as NSString).doubleValue | |
if argumentAsDouble > 0.0 { | |
volume = argumentAsDouble | |
} | |
} | |
// MARK: - Important Constants & Enums | |
let kDimensionUnits = "m" | |
let kDimensionHeight = "height" | |
let kDimensionWidth = "width" | |
let kDimensionDepth = "depth" | |
let kDimensionRadius = "radius" | |
enum ContainerShape: String { | |
case Cube = "Cube" | |
case Sphere = "Sphere" | |
case Cylinder = "Cylinder" | |
case Cone = "Cone" | |
} | |
// MARK: - NumberFormatter | |
var numberFormatter = NSNumberFormatter() | |
numberFormatter.maximumSignificantDigits = { | |
var numberOfSigDigs = 0 | |
for character in volume.description { | |
if character != "." { | |
numberOfSigDigs++ | |
} | |
} | |
return numberOfSigDigs | |
}() | |
// MARK: - Utility Functions | |
/// Computes the height, width, & depth of a cube for a given volume. | |
func computeDimensionsForCubeWithVolume(volume: Double) -> [String:Double] { | |
let aSide = cbrt(volume) | |
return [kDimensionHeight:aSide, kDimensionWidth: aSide, kDimensionDepth: aSide] | |
} | |
/// Computes the radius of a sphere for a given volume. | |
func computeDimensionsForSphereWithVolume(volume: Double) -> [String:Double] { | |
let radius = cbrt( ( 3.0 * volume ) / ( 4.0 * M_PI ) ) | |
return [kDimensionRadius:radius] | |
} | |
/// Computes the height & radius of a cylinder with minimum surface area for given volume. | |
func computeDimensionsForCylinderWithVolume(volume: Double) -> [String:Double] { | |
/* | |
Note on calculations: | |
We know the desired volume of the cylinder but not the desired dimensions. | |
This is an equation with two unknowns and in the Real numbers could have many | |
possible solutions. To narrow it down to one, we are going to use a little | |
calculus to minimize the surface area and thus give us the appropriate | |
radius & height for the given volume. | |
User copper.hat gives a great explanation behind getting the correct formulae | |
for the radius and height ( http://math.stackexchange.com/a/584770 ). | |
*/ | |
let radius = cbrt(volume / (2 * M_PI)) | |
let height = cbrt((4 * volume) / M_PI) | |
return [kDimensionRadius:radius,kDimensionHeight:height] | |
} | |
/// Computes the height & radius of a cone with a slant angle of 45º for given volume. | |
func computeDimensionsForConeWithVolume(volume: Double) -> [String:Double] { | |
/* | |
Note on calculations: | |
We know the desired volume of the cone but not the desired dimensions. | |
This is an equation with two unknowns and in the Real numbers could have many | |
possible solutions. To narrow it down to one, we are going to assume that | |
height and radius are equal, giving us a slant angle of 45º. | |
We could make any number of assumptions (desired slant angle, maximum height, | |
maximum radius, etc) but this one was chosen for simplicity. | |
V = ( h * pi * r^2 ) / 3 ... but h = r so | |
= ( pi * r^3 ) / 3 ... and solving for r gives us... | |
*/ | |
let radius = cbrt((3 * volume) / M_PI) | |
return [kDimensionRadius:radius,kDimensionHeight:radius] | |
} | |
// Given a set of dimensions & shape, properly formats the string for output. | |
func formatDimensions(dimensions: [String:Double], forShape shape: ContainerShape) -> String { | |
switch shape { | |
case .Cube: | |
let height = numberFormatter.stringFromNumber(dimensions[kDimensionHeight]!)! | |
let width = numberFormatter.stringFromNumber(dimensions[kDimensionWidth]!)! | |
let depth = numberFormatter.stringFromNumber(dimensions[kDimensionDepth]!)! | |
return "\(shape.rawValue): \(height) \(kDimensionUnits) \(kDimensionHeight), \(width) \(kDimensionUnits) \(kDimensionWidth), \(depth) \(kDimensionUnits) \(kDimensionDepth)" | |
case .Cone, .Cylinder: | |
let radius = numberFormatter.stringFromNumber(dimensions[kDimensionRadius]!)! | |
let height = numberFormatter.stringFromNumber(dimensions[kDimensionHeight]!)! | |
return "\(shape.rawValue): \(radius) \(kDimensionUnits) \(kDimensionRadius),\(height) \(kDimensionUnits) \(kDimensionHeight)" | |
case .Sphere: | |
let radius = numberFormatter.stringFromNumber(dimensions[kDimensionRadius]!)! | |
return "\(shape.rawValue): \(radius) \(kDimensionUnits) \(kDimensionRadius)" | |
} | |
} | |
// MARK: - Primary Function | |
/// Function computes possible dimensions for the passed in shape & volume. Computed values are returned in a dictionary. | |
func computeDimensions(forShape shape: ContainerShape, withVolume volume: Double) -> String { | |
switch shape { | |
case .Cube: | |
return formatDimensions(computeDimensionsForCubeWithVolume(volume), forShape: .Cube) | |
case .Cone: | |
return formatDimensions(computeDimensionsForConeWithVolume(volume), forShape: .Cone) | |
case .Cylinder: | |
return formatDimensions(computeDimensionsForCylinderWithVolume(volume), forShape: .Cylinder) | |
case .Sphere: | |
return formatDimensions(computeDimensionsForSphereWithVolume(volume), forShape: .Sphere) | |
} | |
} | |
// -------------------------------------------------- | |
// MARK: - Comput & Output to User | |
println("\n\nContainer Dimensions for a given volume of \(volume) \(kDimensionUnits)^3") | |
println("----------------------------------------------------------") | |
println("\(computeDimensions(forShape: .Cube, withVolume: volume))") | |
println("\(computeDimensions(forShape: .Cone, withVolume: volume))") | |
println("\(computeDimensions(forShape: .Cylinder, withVolume: volume))") | |
println("\(computeDimensions(forShape: .Sphere, withVolume: volume))") | |
println("----------------------------------------------------------\n\n") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment