Maximum Perimeter Triangle
HackerRank posted a simple problem that just requires some basic geometry knowledge, any sorting technique, and attention to details. The problem is called Maximum Perimeter Triangle and it is important to pay attention to the details of the question being asked:
- The number of sides is small, 50
- The basic geometry rule to be applied is that given 3 numbers a, b and c with a <= b <= c, a triangle can only be formed with these 3 numbers IIF a < b + c
- Each side can go all the way up to 10^9. Better to use a long to store them
- Given requirements (1) and (2) in the question, it is better to sort the input in descending order. Since n = 50, any sorting technique works, even bubble-sort (50^2 = 2500)
That's it, rest is a straightforward implementation, which works when submitted:
Code is below, cheers, Marcelo.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;
namespace HackerRank
{
class Program
{
static void Main(string[] args)
{
int n = Int32.Parse(Console.ReadLine());
string[] sides_temp = Console.ReadLine().Split(' ');
long[] sides = Array.ConvertAll(sides_temp, Int64.Parse);
bool sorted = false;
while (!sorted)
{
sorted = true;
for (int i = 0; i < n - 1; i++)
{
if (sides[i] < sides[i + 1])
{
long temp = sides[i];
sides[i] = sides[i + 1];
sides[i + 1] = temp;
sorted = false;
}
}
}
long maxPerimeter = Int64.MinValue;
long side1 = -1;
long side2 = -1;
long side3 = -1;
for (int s1 = 0; s1 < n; s1++)
{
for (int s2 = s1 + 1; s2 < n; s2++)
{
for (int s3 = s2 + 1; s3 < n; s3++)
{
if (sides[s1] < sides[s2] + sides[s3])
{
long perimeter = sides[s1] + sides[s2] + sides[s3];
if (perimeter > maxPerimeter)
{
maxPerimeter = perimeter;
side1 = sides[s1];
side2 = sides[s2];
side3 = sides[s3];
}
else if (perimeter == maxPerimeter)
{
if (sides[s1] > side1)
{
maxPerimeter = perimeter;
side1 = sides[s1];
side2 = sides[s2];
side3 = sides[s3];
}
else if (sides[s1] == side1)
{
if (sides[s3] > side3)
{
maxPerimeter = perimeter;
side1 = sides[s1];
side2 = sides[s2];
side3 = sides[s3];
}
}
}
}
}
}
}
if (maxPerimeter == Int64.MinValue)
{
Console.WriteLine(-1);
}
else
{
Console.WriteLine("{0} {1} {2}", side3, side2, side1);
}
}
}
}
Here are few details to keep in mind:Given sticks of lengths , use of the sticks to construct a non-degenerate triangle with the maximum possible perimeter. Then print the lengths of its sides as space-separated integers in non-decreasing order.If there are several valid triangles having the maximum perimeter:
- Choose the one with the longest maximum side (i.e., the largest value for the longest side of any valid triangle having the maximum perimeter).
- If more than one such triangle meets the first criterion, choose the one with the longest minimum side (i.e., the largest value for the shortest side of any valid triangle having the maximum perimeter).
- If more than one such triangle meets the second criterion, print any one of the qualifying triangles.
If no non-degenerate triangle exists, print-1
.
- The number of sides is small, 50
- The basic geometry rule to be applied is that given 3 numbers a, b and c with a <= b <= c, a triangle can only be formed with these 3 numbers IIF a < b + c
- Each side can go all the way up to 10^9. Better to use a long to store them
- Given requirements (1) and (2) in the question, it is better to sort the input in descending order. Since n = 50, any sorting technique works, even bubble-sort (50^2 = 2500)
That's it, rest is a straightforward implementation, which works when submitted:
Code is below, cheers, Marcelo.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;
namespace HackerRank
{
class Program
{
static void Main(string[] args)
{
int n = Int32.Parse(Console.ReadLine());
string[] sides_temp = Console.ReadLine().Split(' ');
long[] sides = Array.ConvertAll(sides_temp, Int64.Parse);
bool sorted = false;
while (!sorted)
{
sorted = true;
for (int i = 0; i < n - 1; i++)
{
if (sides[i] < sides[i + 1])
{
long temp = sides[i];
sides[i] = sides[i + 1];
sides[i + 1] = temp;
sorted = false;
}
}
}
long maxPerimeter = Int64.MinValue;
long side1 = -1;
long side2 = -1;
long side3 = -1;
for (int s1 = 0; s1 < n; s1++)
{
for (int s2 = s1 + 1; s2 < n; s2++)
{
for (int s3 = s2 + 1; s3 < n; s3++)
{
if (sides[s1] < sides[s2] + sides[s3])
{
long perimeter = sides[s1] + sides[s2] + sides[s3];
if (perimeter > maxPerimeter)
{
maxPerimeter = perimeter;
side1 = sides[s1];
side2 = sides[s2];
side3 = sides[s3];
}
else if (perimeter == maxPerimeter)
{
if (sides[s1] > side1)
{
maxPerimeter = perimeter;
side1 = sides[s1];
side2 = sides[s2];
side3 = sides[s3];
}
else if (sides[s1] == side1)
{
if (sides[s3] > side3)
{
maxPerimeter = perimeter;
side1 = sides[s1];
side2 = sides[s2];
side3 = sides[s3];
}
}
}
}
}
}
}
if (maxPerimeter == Int64.MinValue)
{
Console.WriteLine(-1);
}
else
{
Console.WriteLine("{0} {1} {2}", side3, side2, side1);
}
}
}
}
My solution:
ReplyDelete#include
#include
#include
#include
using namespace std;
bool is_valid(int a, int b, int c) {
return (a+b > c) && (a+c > b) && (b+c > a);
}
int main() {
int n; cin >> n;
vector sticks(n);
for (int i = 0; i < n; ++i) {
cin >> sticks[i];
}
sort(sticks.begin(), sticks.end());
for (int i = sticks.size()-1; i >= 2; --i) {
if (is_valid(sticks[i-2], sticks[i-1], sticks[i])) {
cout << sticks[i-2] << " " << sticks[i-1] << " " << sticks[i] << endl;
return 0;
}
}
cout << -1 << endl;
return 0;
}
or a human-readable version - https://ideone.com/mnwzy9 :)
Cheers,
Taras