diff --git a/.gitignore b/.gitignore
index e70ce39..8eb8d3d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,7 @@ obj/
[Dd]ebug*/
[Rr]elease*/
Ankh.NoLoad
+.vs/
#MonoDevelop
*.pidb
@@ -77,7 +78,6 @@ packages/
*.testsettings
#only allow code
-.vcxproj
.users
.filters
.txt
diff --git a/AGenericProblem.cs b/AGenericProblem.cs
new file mode 100644
index 0000000..4e708e5
--- /dev/null
+++ b/AGenericProblem.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Contest
+{
+ public abstract class AGenericProblem : IProblem
+ {
+ protected abstract void ReadInput(StreamReader reader);
+
+ public void Run()
+ {
+ StreamReader reader = null;
+ StreamWriter writer = null;
+ try
+ {
+ reader = new StreamReader("input.txt");
+ writer = new StreamWriter("output.txt");
+
+ int problemCount = Converters.ParseInt(reader.ReadLine());
+ for (int problemIndex = 1; problemIndex <= problemCount; problemIndex++)
+ {
+ ReadInput(reader);
+ writer.WriteLine("Case #{0}: ", problemIndex);
+ SolveAndWrite(problemIndex, writer);
+ }
+ }
+ catch (Exception e)
+ {
+ String msg = "Exception: " + e;
+ Console.WriteLine(msg);
+ Debug.Fail(msg);
+ }
+ finally
+ {
+ if (reader != null)
+ reader.Dispose();
+ if (writer != null)
+ writer.Dispose();
+ }
+ }
+
+ protected abstract string SolveAndWrite(int problemIndex, StreamWriter writer);
+ }
+}
diff --git a/ALineProblem.cs b/ALineProblem.cs
new file mode 100644
index 0000000..8cdfb57
--- /dev/null
+++ b/ALineProblem.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Contest
+{
+ public abstract class ALineProblem : IProblem
+ {
+ public void Run()
+ {
+ StreamReader reader = null;
+ StreamWriter writer = null;
+ try
+ {
+ reader = new StreamReader("input.txt");
+ writer = new StreamWriter("output.txt");
+
+ int problemCount = Converters.ParseInt(reader.ReadLine());
+ for (int problemIndex = 1; problemIndex <= problemCount; problemIndex++)
+ {
+ string line = reader.ReadLine();
+ string result = SolveProblem(problemIndex, line);
+ writer.WriteLine("Case #{0}: {1}", problemIndex, result);
+ }
+ }
+ catch (Exception e)
+ {
+ String msg = "Exception: " + e;
+ Console.WriteLine(msg);
+ Debug.Fail(msg);
+ }
+ finally
+ {
+ if (reader != null)
+ reader.Dispose();
+ if (writer != null)
+ writer.Dispose();
+ }
+ }
+
+ protected abstract string SolveProblem(int problemIndex, string line);
+ }
+}
diff --git a/App.config b/App.config
new file mode 100644
index 0000000..731f6de
--- /dev/null
+++ b/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Contest.csproj b/Contest.csproj
new file mode 100644
index 0000000..6f2f4fa
--- /dev/null
+++ b/Contest.csproj
@@ -0,0 +1,53 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {14C05281-A66C-45A1-8DE5-A0C869489557}
+ Exe
+ Contest
+ Contest
+ v4.6.1
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Contest.sln b/Contest.sln
new file mode 100644
index 0000000..a0365ce
--- /dev/null
+++ b/Contest.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27130.2027
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contest", "Contest.csproj", "{14C05281-A66C-45A1-8DE5-A0C869489557}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {14C05281-A66C-45A1-8DE5-A0C869489557}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {14C05281-A66C-45A1-8DE5-A0C869489557}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {14C05281-A66C-45A1-8DE5-A0C869489557}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {14C05281-A66C-45A1-8DE5-A0C869489557}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {07DBA281-E58E-498B-81AA-5172988DF5C7}
+ EndGlobalSection
+EndGlobal
diff --git a/Converters.cs b/Converters.cs
new file mode 100644
index 0000000..dac619d
--- /dev/null
+++ b/Converters.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Contest
+{
+ public static class Converters
+ {
+ private static readonly IFormatProvider formatProvider = CultureInfo.InvariantCulture;
+
+ public static int ParseInt(string value)
+ {
+ return Int32.Parse(value, formatProvider);
+ }
+ }
+}
diff --git a/GCJ2017_B_TidyNumbers.cs b/GCJ2017_B_TidyNumbers.cs
new file mode 100644
index 0000000..70f199c
--- /dev/null
+++ b/GCJ2017_B_TidyNumbers.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Contest
+{
+ public class GCJ2017_B_TidyNumbers : ALineProblem
+ {
+ protected override string SolveProblem(int problemIndex, string line)
+ {
+ // Read data
+ int n = line.Length;
+ int[] digits = new int[n];
+ for (int i = 0; i < n; i++)
+ {
+ digits[i] = line[i] - '0';
+ }
+
+ // Solve
+ while (true)
+ {
+ bool restart = false;
+ for (int i = 0; i < n - 1; i++)
+ {
+ if (digits[i] > digits[i + 1])
+ {
+ digits[i]--;
+ for (int j = i + 1; j < n; j++)
+ digits[j] = 9;
+ restart = true;
+ break;
+ }
+ }
+
+ if (!restart)
+ break;
+ }
+ // Print
+ StringBuilder sb = new StringBuilder();
+ int start = (digits[0] == 0) ? 1 : 0;
+ for (int i = start; i < n; i++)
+ {
+ sb.Append(digits[i]);
+ }
+ string result = sb.ToString();
+ return result;
+ }
+ }
+}
diff --git a/GCJ2017_D_FashionShow.cs b/GCJ2017_D_FashionShow.cs
new file mode 100644
index 0000000..e690457
--- /dev/null
+++ b/GCJ2017_D_FashionShow.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Contest
+{
+ public class GCJ2017_D_FashionShow : AGenericProblem
+ {
+ private int N;
+ private int M;
+ private char[,] data;
+
+ protected override void ReadInput(StreamReader reader)
+ {
+ string line = reader.ReadLine();
+ string[] parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+ N = Converters.ParseInt(parts[0]);
+ M = Converters.ParseInt(parts[1]);
+
+ data = new char[N, N];
+ for (int i = 0; i < M; i++)
+ {
+ line = reader.ReadLine();
+ parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+ char c = parts[0][0];
+ int rowIndex = Converters.ParseInt(parts[1]);
+ int colIndex = Converters.ParseInt(parts[2]);
+ data[rowIndex, colIndex] = c;
+ }
+ }
+
+ protected override string SolveAndWrite(int problemIndex, StreamWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/GCJ2018_Practice_SenateEvacuation.cs b/GCJ2018_Practice_SenateEvacuation.cs
new file mode 100644
index 0000000..5c523b2
--- /dev/null
+++ b/GCJ2018_Practice_SenateEvacuation.cs
@@ -0,0 +1,366 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+
+namespace Contest
+{
+ class Party : IComparable
+ {
+ public int index;
+ public int count;
+
+ public char Name { get { return (char)('A' + index); } }
+
+ public Party(int index, int count)
+ {
+ this.index = index;
+ this.count = count;
+ }
+
+ public int CompareTo(Party other)
+ {
+ return count.CompareTo(other.count);
+ }
+ }
+
+ public class GCJ2018_Problem
+ {
+ private int n;
+ private int[] parties;
+ private Heap heap;
+
+ protected void ReadInput(StreamReader reader)
+ {
+ n = Helper.ParseInt(reader.ReadLine());
+ parties = Helper.ParseInts(reader.ReadLine());
+ }
+
+ protected void SolveAndWrite(int problemIndex, StreamWriter writer)
+ {
+ heap = new Heap(HeapType.Max);
+ for (int i = 0; i < parties.Length; i++)
+ heap.Insert(new Party(i, parties[i]));
+
+ List evacuation = new List();
+
+ Party party;
+ while (heap.Count > 2)
+ {
+ party = heap.Remove();
+ if (party.count >= 2)
+ {
+ evacuation.Add(party.index);
+ evacuation.Add(party.index);
+ party.count -= 2;
+ }
+ else
+ {
+ evacuation.Add(party.index);
+ party.count++;
+ }
+
+ if (party.count > 0)
+ {
+ heap.Insert(party);
+ }
+ }
+
+ if (heap.Count == 2)
+ {
+ Party[] last = new Party[2];
+ last[0] = heap.Remove();
+ last[1] = heap.Remove();
+ }
+ else if (heap.Count == 1)
+ {
+ party = heap.Remove();
+ while (party.count > 0)
+ {
+ party.count--;
+ evacuation.Add(party.index);
+ }
+ }
+ }
+
+ public void Run()
+ {
+ StreamReader reader = null;
+ StreamWriter writer = null;
+ try
+ {
+ reader = new StreamReader("input.txt");
+ writer = new StreamWriter("output.txt");
+
+ int problemCount = ParseInt(reader.ReadLine());
+ for (int problemIndex = 1; problemIndex <= problemCount; problemIndex++)
+ {
+ ReadInput(reader);
+ writer.WriteLine("Case #{0}: ", problemIndex);
+ SolveAndWrite(problemIndex, writer);
+ }
+ }
+ catch (Exception e)
+ {
+ String msg = "Exception: " + e;
+ Console.WriteLine(msg);
+ Debug.Fail(msg);
+ }
+ finally
+ {
+ if (reader != null)
+ reader.Dispose();
+ if (writer != null)
+ writer.Dispose();
+ }
+ }
+ }
+
+ public class Helper
+ {
+ ///
+ /// Run one problem at a time.
+ /// Just initialize the solver with the correct one.
+ ///
+ public static void Main(string[] args)
+ {
+ GCJ2018_Problem instance = new GCJ2018_Problem();
+ instance.Run();
+ }
+
+ public static int ParseInt(string value)
+ {
+ return Int32.Parse(value, formatProvider);
+ }
+
+ public static int[] ParseInts(string line)
+ {
+ string[] parts = line.Split(' ');
+ int[] result = new int[parts.Length];
+ for (int i = 0; i < parts.Length; i++)
+ {
+ result[i] = ParseInt(parts[i]);
+ }
+ return result;
+ }
+
+ private static readonly IFormatProvider formatProvider = CultureInfo.InvariantCulture;
+ }
+
+ public enum HeapType
+ {
+ Max,
+ Min
+ }
+
+ public sealed class Heap where T : IComparable
+ {
+ internal delegate bool IndexComparor(int childIx, int parentIx);
+ internal IndexComparor IsHigherPriorityThanParent;
+
+ ///
+ /// Constructs a new max heap.
+ ///
+ public Heap() : this(HeapType.Max) { }
+
+ ///
+ /// Constructs a new heap with the given type, allowing you to specify if this heap will be a min or a max heap.
+ ///
+ ///
+ public Heap(HeapType type)
+ {
+ this.List = new List();
+ this.Init(type);
+ }
+
+ ///
+ /// Constructs a new heap with the given type and initial capacity.
+ ///
+ /// The type of heap that determines if it will be a min or max heap.
+ /// The initial capacity of the heap.
+ public Heap(HeapType type, int capacity)
+ {
+ this.List = new List(capacity);
+ this.Init(type);
+ }
+
+ ///
+ /// Initializes some properties of the tree
+ ///
+ ///
+ private void Init(HeapType type)
+ {
+ this.Type = type;
+
+ if (type == HeapType.Max)
+ this.IsHigherPriorityThanParent = this.IsLargerThan;
+ else
+ this.IsHigherPriorityThanParent = this.IsSmallerThanParent;
+ }
+
+ ///
+ /// Identifies the heap as either being a max heap or a min heap
+ ///
+ public HeapType Type { get; private set; }
+
+ internal List List { get; set; }
+
+ ///
+ /// Returns the number of items in the heap
+ ///
+ public int Count { get { return this.List.Count; } }
+
+ ///
+ /// Given an index of a node, this method returns the index of that node's parent
+ ///
+ internal static int ParentIndexOf(int ix)
+ {
+ if (ix == 0)
+ throw new InvalidOperationException("ParentOfRootDoesntExist");
+ else
+ {
+ return (int)Math.Floor((double)(ix - 1) / 2);
+ }
+ }
+
+ ///
+ /// Given an index of a node, this method returns the index of that node's left child
+ ///
+ internal static int LeftChildIndexOf(int ix)
+ {
+ return (2 * ix) + 1;
+ }
+
+ ///
+ /// Given an index of a node, this method returns the index of that node's right child
+ ///
+ internal static int RightChildIndexOf(int ix)
+ {
+ return (2 * ix) + 2;
+ }
+
+ ///
+ /// Returns true if the value of the node at the first index is larger than the value of the node at the second index.
+ ///
+ /// The index of the first value
+ /// The index of the second value
+ internal bool IsLargerThan(int first, int second)
+ {
+ return this.List[first].CompareTo(this.List[second]) > 0;
+ }
+
+ ///
+ /// Returns true if the value of the node at the first index is smaller than the value of the node at the second index.
+ ///
+ /// The index of the first value
+ /// The index of the second value
+ internal bool IsSmallerThanParent(int first, int second)
+ {
+ return this.List[first].CompareTo(this.List[second]) < 0;
+ }
+
+ ///
+ /// Swaps the value at index ix1 with the value at index ix2
+ ///
+ internal void Swap(int ix1, int ix2)
+ {
+ T temp = this.List[ix1];
+ this.List[ix1] = this.List[ix2];
+ this.List[ix2] = temp;
+ }
+
+ ///
+ /// Inserts the given value into the heap, maintaining the heap property as defined by Heap.HeapType
+ ///
+ public void Insert(T value)
+ {
+ int insertedAtIndex = this.List.Count;
+ this.List.Add(value);
+ this.HeapifyUp(insertedAtIndex);
+ }
+
+ ///
+ /// Helper function that takes the node inserted at insertedIx and makes sure it is bubbled up to the correct place in the heap.
+ ///
+ internal void HeapifyUp(int insertedIx)
+ {
+ int currentIx = insertedIx;
+
+ while (currentIx > 0)
+ {
+ int parentIx = ParentIndexOf(currentIx);
+ if (this.IsHigherPriorityThanParent(currentIx, parentIx))
+ this.Swap(currentIx, parentIx);
+ else
+ break;
+
+ currentIx = parentIx;
+ }
+ }
+
+ ///
+ /// Removes the node at the top of the heap and returns its value.
+ ///
+ /// The largest node in the heap if the HeapType = Max, the smallest node in the heap if the HeapType = Min
+ public T Remove()
+ {
+ int lastIx = this.List.Count - 1;
+ T result = default(T);
+ if (lastIx < 0)
+ throw new InvalidOperationException("Cannot remove from empty heap");
+ else
+ {
+ result = this.List[0];
+
+ if (lastIx > 0)
+ this.List[0] = this.List[lastIx];
+
+ this.List.RemoveAt(lastIx);
+ this.HeapifyDown();
+ }
+
+ return result;
+ }
+
+ ///
+ /// Starting at the top of the heap, examines all nodes underneath it ensuring that the heap property is maintained at all nodes.
+ ///
+ internal void HeapifyDown()
+ {
+ int parentIx = 0;
+ while (parentIx < this.Count)
+ {
+ int leftIx = LeftChildIndexOf(parentIx);
+ int rightIx = RightChildIndexOf(parentIx);
+ int largest = parentIx;
+
+ if (leftIx < this.Count && this.IsHigherPriorityThanParent(leftIx, largest))
+ largest = leftIx;
+
+ if (rightIx < this.Count && this.IsHigherPriorityThanParent(rightIx, largest))
+ largest = rightIx;
+
+ if (largest != parentIx)
+ {
+ this.Swap(largest, parentIx);
+ parentIx = largest;
+ }
+ else
+ break;
+ }
+ }
+
+ ///
+ /// Returns the value of the node at the top of the heap without removing it.
+ ///
+ public T Peek()
+ {
+ if (this.List.Count > 0)
+ return this.List[0];
+ else
+ throw new InvalidOperationException("Empty heap");
+ }
+ }
+}
diff --git a/GCJ2018_Problem.cs b/GCJ2018_Problem.cs
new file mode 100644
index 0000000..e9e9767
--- /dev/null
+++ b/GCJ2018_Problem.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+
+namespace Contest
+{
+ public class GCJ2018_Problem
+ {
+ private static readonly IFormatProvider formatProvider = CultureInfo.InvariantCulture;
+
+ protected void ReadInput(StreamReader reader)
+ {
+
+ }
+
+ protected void SolveAndWrite(int problemIndex, StreamWriter writer)
+ {
+
+ }
+
+ public void Run()
+ {
+ StreamReader reader = null;
+ StreamWriter writer = null;
+ try
+ {
+ reader = new StreamReader("input.txt");
+ writer = new StreamWriter("output.txt");
+
+ int problemCount = ParseInt(reader.ReadLine());
+ for (int problemIndex = 1; problemIndex <= problemCount; problemIndex++)
+ {
+ ReadInput(reader);
+ writer.WriteLine("Case #{0}: ", problemIndex);
+ SolveAndWrite(problemIndex, writer);
+ }
+ }
+ catch (Exception e)
+ {
+ String msg = "Exception: " + e;
+ Console.WriteLine(msg);
+ Debug.Fail(msg);
+ }
+ finally
+ {
+ if (reader != null)
+ reader.Dispose();
+ if (writer != null)
+ writer.Dispose();
+ }
+ }
+
+
+ public static int ParseInt(string value)
+ {
+ return Int32.Parse(value, formatProvider);
+ }
+
+ public static int[] ParseInts(string line)
+ {
+ string[] parts = line.Split(' ');
+ int[] result = new int[parts.Length];
+ for (int i = 0; i < parts.Length; i++)
+ {
+ result[i] = ParseInt(parts[i]);
+ }
+ return result;
+ }
+
+ ///
+ /// Run one problem at a time.
+ /// Just initialize the solver with the correct one.
+ ///
+ public static void Main(string[] args)
+ {
+ GCJ2018_Problem instance = new GCJ2018_Problem();
+ instance.Run();
+ }
+ }
+}
diff --git a/GCJ2018_Qual_CubicUFO.cs b/GCJ2018_Qual_CubicUFO.cs
new file mode 100644
index 0000000..f101dfb
--- /dev/null
+++ b/GCJ2018_Qual_CubicUFO.cs
@@ -0,0 +1,286 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+
+namespace Contest
+{
+ public struct Point2D
+ {
+ private readonly double _x, _y;
+
+ public double X { get { return _x; } }
+ public double Y { get { return _y; } }
+
+ public Point2D(double x, double y)
+ {
+ _x = x;
+ _y = y;
+ }
+
+ public static double DistanceSquare(Point2D p1, Point2D p2)
+ {
+ return (p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y);
+ }
+
+ public static double Distance(Point2D p1, Point2D p2)
+ {
+ return Math.Sqrt(DistanceSquare(p1, p2));
+ }
+
+ public static Point2D MiddlePoint(Point2D p1, Point2D p2)
+ {
+ return new Point2D(0.5 * (p1.X + p2.X), 0.5 * (p1.Y + p2.Y));
+ }
+
+ public override string ToString()
+ {
+ return String.Format(Helper.FormatProvider, "({0}, {1})", X, Y);
+ }
+ }
+
+ public struct Vector3D
+ {
+ private double _x, _y, _z;
+
+ public double X { get { return _x; } }
+ public double Y { get { return _y; } }
+ public double Z { get { return _z; } }
+
+ public Vector3D(double x, double y, double z)
+ {
+ _x = x;
+ _y = y;
+ _z = z;
+ }
+ }
+
+ public class GCJ2018_Problem
+ {
+ private static readonly double SQRT2 = Math.Sqrt(2.0);
+
+ private double A;
+
+ private static Vector3D[] GetVectors1Plane()
+ {
+ return new Vector3D[]
+ {
+ new Vector3D(0.5, 0.0, 0.0),
+ new Vector3D(0.0, 0.5, 0.0),
+ new Vector3D(0.0, 0.0, 0.5),
+ };
+ }
+
+ private static Vector3D[] GetVectors2Planes(double area)
+ {
+ Vector3D[] vectors = GetVectors2Planes(SQRT2);
+
+ area = area - SQRT2;
+
+ double areaSQ;
+ double sideSQ;
+ if (Math.Abs(SQRT2 - area) < 0.000001)
+ {
+ area = SQRT2;
+ areaSQ = 2;
+ sideSQ = 0;
+ }
+ else
+ {
+ areaSQ = area * area;
+ sideSQ = 2.0 - areaSQ;
+ }
+
+ double hP1 = Math.Sqrt(sideSQ);
+ Point2D p1 = new Point2D(-0.5 * area, 0.5 * hP1);
+ Point2D p2 = new Point2D(0.5 * area, -0.5 * hP1);
+
+ // Dot Product is zero => p1.x * p3.x + p1.y * p3.y == 0
+ double p3x = p1.Y / p1.X;
+ double p3y = -1.0;
+ double p3len = Math.Sqrt(2.0 * (p3x * p3x + 1));
+ Point2D p3 = new Point2D(p3x / p3len, p3y / p3len);
+ Point2D p13mid = Point2D.MiddlePoint(p1, p3);
+ Point2D p23mid = Point2D.MiddlePoint(p2, p3);
+
+ return new Vector3D[]
+ {
+ new Vector3D(0.3535533905932738, 0.3535533905932738, 0.0),
+ new Vector3D(-0.3535533905932738, 0.3535533905932738, 0.0),
+ new Vector3D(0.0, 0.0, 0.5),
+ };
+ }
+
+ private static Vector3D[] GetVectors3Planes(double area)
+ {
+ double areaSQ;
+ double sideSQ;
+ if (Math.Abs(SQRT2 - area) < 0.000001)
+ {
+ area = SQRT2;
+ areaSQ = 2;
+ sideSQ = 0;
+ }
+ else
+ {
+ areaSQ = area * area;
+ sideSQ = 2.0 - areaSQ;
+ }
+
+ double hP1 = Math.Sqrt(sideSQ);
+ Point2D p1 = new Point2D(-0.5 * area, 0.5 * hP1);
+ Point2D p2 = new Point2D(0.5 * area, -0.5 * hP1);
+
+ // Dot Product is zero => p1.x * p3.x + p1.y * p3.y == 0
+ double p3x = p1.Y / p1.X;
+ double p3y = -1.0;
+ double p3len = Math.Sqrt(2.0 * (p3x * p3x + 1));
+ Point2D p3 = new Point2D(p3x / p3len, p3y / p3len);
+ Point2D p13mid = Point2D.MiddlePoint(p1, p3);
+ Point2D p23mid = Point2D.MiddlePoint(p2, p3);
+
+ return new Vector3D[]
+ {
+ new Vector3D(p13mid.X, p13mid.Y, 0.0),
+ new Vector3D(p23mid.X, p23mid.Y, 0.0),
+ new Vector3D(0.0, 0.0, 0.5),
+ };
+ }
+
+ private static double CalculateSideInRect(double hypotenuse, double otherSide)
+ {
+ if (Math.Abs(hypotenuse - otherSide) < 0.000001)
+ return 0.0;
+ double side = Math.Sqrt(hypotenuse * hypotenuse - otherSide * otherSide);
+ return side;
+ }
+
+ private double[] Rotate(double x, double y, double angle)
+ {
+ double ca = Math.Cos(angle);
+ double sa = Math.Sin(angle);
+ return new double[] { ca * x - sa * y, sa * x + ca * y };
+ }
+
+ private double[] SolveQuadraticEquation(double a, double b, double c)
+ {
+ double[] r = new double[]
+ {
+ (-b + Math.Sqrt(b * b - 4 * a * c)) / (2 * a),
+ (-b - Math.Sqrt(b * b - 4 * a * c)) / (2 * a),
+ };
+ return r;
+ }
+
+ protected void SolveAndWrite(int problemIndex, TextWriter writer)
+ {
+ Vector3D[] vectors = null;
+
+ if(A == 1.0)
+ {
+ vectors = GetVectors1Plane();
+ }
+ else if(A <= 1.414213f)
+ {
+ vectors = GetVectors2Planes(A);
+ }
+ else
+ {
+
+ }
+ foreach (Vector3D vector in vectors)
+ {
+ writer.WriteLine();
+ writer.Write(String.Format(Helper.FormatProvider, "{0} {1} {2}", vector.X, vector.Y, vector.Z));
+ }
+ }
+
+ protected void ReadInput(TextReader reader)
+ {
+ A = Helper.ParseFloat(reader.ReadLine());
+ }
+
+ public void Run()
+ {
+ TextReader reader = null;
+ TextWriter writer = null;
+ try
+ {
+ reader = new StreamReader("input.txt");
+ writer = new StreamWriter("output.txt");
+ //reader = Console.In;
+ //writer = Console.Out;
+
+ int problemCount = Helper.ParseInt(reader.ReadLine());
+ for (int problemIndex = 1; problemIndex <= problemCount; problemIndex++)
+ {
+ ReadInput(reader);
+ writer.Write("Case #{0}:", problemIndex);
+ SolveAndWrite(problemIndex, writer);
+ writer.WriteLine();
+ }
+ }
+ catch (Exception e)
+ {
+ String msg = "Exception: " + e;
+ Console.WriteLine(msg);
+ Debug.Fail(msg);
+ }
+ finally
+ {
+ if (reader != null)
+ reader.Dispose();
+ if (writer != null)
+ writer.Dispose();
+ }
+ }
+ }
+
+ public class Helper
+ {
+ ///
+ /// Run one problem at a time.
+ /// Just initialize the solver with the correct one.
+ ///
+ public static void Main(string[] args)
+ {
+ GCJ2018_Problem instance = new GCJ2018_Problem();
+ instance.Run();
+ }
+
+ public static int ParseInt(string value)
+ {
+ return Int32.Parse(value, FormatProvider);
+ }
+
+ public static double ParseDouble(string value)
+ {
+ return Double.Parse(value, FormatProvider);
+ }
+
+ public static float ParseFloat(string value)
+ {
+ return Single.Parse(value, FormatProvider);
+ }
+
+ public static int[] ParseInts(string line)
+ {
+ string[] parts = line.Split(' ');
+ int[] result = new int[parts.Length];
+ for (int i = 0; i < parts.Length; i++)
+ {
+ result[i] = ParseInt(parts[i]);
+ }
+ return result;
+ }
+
+ public static string ToStr(double v)
+ {
+ return v.ToString(FormatProvider);
+ }
+
+ public static readonly IFormatProvider FormatProvider = CultureInfo.InvariantCulture;
+ }
+}
diff --git a/GCJ2018_Qual_GoGopher.cs b/GCJ2018_Qual_GoGopher.cs
new file mode 100644
index 0000000..475eaff
--- /dev/null
+++ b/GCJ2018_Qual_GoGopher.cs
@@ -0,0 +1,605 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+///
+/// The Gopher will be deployed in a Divide and Conquer manner.
+///
+namespace Contest
+{
+ public class Rect
+ {
+ private readonly int _x, _y;
+ private readonly int _lx, _ly;
+
+ public Rect(int x, int y, int lx, int ly)
+ {
+ _x = x;
+ _y = y;
+ _lx = lx;
+ _ly = ly;
+ }
+
+ public Rect GrowToInclude(int x, int y)
+ {
+ int minX = Math.Min(X, x);
+ int minY = Math.Min(Y, y);
+ int maxX = Math.Max(X2, x);
+ int maxY = Math.Max(Y2, y);
+ return new Rect(minX, minY, maxX - minX + 1, maxY - minY + 1);
+ }
+
+ public Rect GrowToInclude(Rect rect)
+ {
+ int minX = Math.Min(_x, rect._x);
+ int minY = Math.Min(_y, rect._y);
+ int maxX = Math.Max(X2, rect.X2);
+ int maxY = Math.Max(Y2, rect.Y2);
+ return new Rect(minX, minY, maxX - minX + 1, maxY - minY + 1);
+ }
+
+ public int MidX { get { return _x + _lx / 2; } }
+
+ public int MidY { get { return _y + _ly / 2; } }
+
+ public int X { get { return _x; } }
+
+ public int Y { get { return _y; } }
+
+ public int X2 { get { return _x + _lx - 1; } }
+
+ public int Y2 { get { return _y + _ly - 1; } }
+
+ public int SizeX { get { return _lx; } }
+
+ public int SizeY { get { return _ly; } }
+
+ public int Area { get { return _lx * _ly; } }
+
+ public int CountIn(int[,] map)
+ {
+ int x2 = X2;
+ int y2 = Y2;
+ int n = 0;
+ for (int i = _x; i <= x2; i++)
+ for (int j = _y; j <= y2; j++)
+ n += map[i, j];
+ return n;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == this)
+ return true;
+ Rect other = (Rect)obj;
+ return _x == other._x
+ && _y == other._y
+ && _lx == other._lx
+ && _ly == other._ly;
+ }
+
+ public override int GetHashCode()
+ {
+ return _x + (_y << 3) + (_lx << 5) + (_ly << 7);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("({0}, {1}) l=[{2}, {3}]", _x, _y, _lx, _ly);
+ }
+
+ public String GetDebugMap(int[,] map)
+ {
+ StringBuilder sb = new StringBuilder();
+ for (int i = X; i <= X2; i++)
+ {
+ for (int j = Y; j <= Y2; j++)
+ sb.Append(map[i, j]);
+
+ sb.AppendLine();
+ }
+ String r = sb.ToString();
+ return r;
+ }
+ }
+
+ public class GCJ2018_Problem
+ {
+ private const int MAX_SIZE = 1000;
+ private const int GOPHER_SIZE = 3;
+
+ private readonly Random rand = new Random();
+
+ private int A;
+ private int[,] map;
+ private Rect[] allowedFills;
+ private int deployCount;
+
+ private static Rect[] GetAllowedFills(int desiredArea)
+ {
+ int avg = (int)Math.Sqrt(desiredArea);
+ int max = Math.Max(avg + 1, GOPHER_SIZE);
+
+ int minA = int.MaxValue;
+ List minFills = new List();
+
+ for (int i = 3; i <= max; i++)
+ {
+ for (int j = 3; j <= max; j++)
+ {
+ int a = i * j;
+ if (a < desiredArea || a > minA)
+ continue;
+
+ if (a < minA)
+ {
+ minA = a;
+ minFills.Clear();
+ }
+ minFills.Add(new Rect(0, 0, i, j));
+ }
+ }
+
+ return minFills.ToArray();
+ }
+
+ private bool IsValidForBestFit(Rect fillRect, Rect rect, Rect[] allowedFills)
+ {
+ Rect increased = fillRect.GrowToInclude(rect);
+ return allowedFills.Any(r => increased.SizeX <= r.SizeX && increased.SizeY <= r.SizeY);
+ }
+
+ private Rect FindBestExt(Rect fillRect, int expectedCount)
+ {
+ int x = fillRect.X;
+ int y = fillRect.Y;
+ int x2 = fillRect.X2;
+ int y2 = fillRect.Y2;
+
+ for (int depth = 1; depth < GOPHER_SIZE; depth++)
+ {
+ // Corners
+ {
+ Rect rect;
+ rect = new Rect(x - depth, y - depth, GOPHER_SIZE, GOPHER_SIZE);
+ if (rect.CountIn(map) == expectedCount && IsValidForBestFit(fillRect, rect, allowedFills))
+ return rect;
+
+ rect = new Rect(x2 - depth, y2 - depth, GOPHER_SIZE, GOPHER_SIZE);
+ if (rect.CountIn(map) == expectedCount && IsValidForBestFit(fillRect, rect, allowedFills))
+ return rect;
+
+ rect = new Rect(x2 - depth, y - depth, GOPHER_SIZE, GOPHER_SIZE);
+ if (rect.CountIn(map) == expectedCount && IsValidForBestFit(fillRect, rect, allowedFills))
+ return rect;
+
+ rect = new Rect(x - depth, y2 - depth, GOPHER_SIZE, GOPHER_SIZE);
+ if (rect.CountIn(map) == expectedCount && IsValidForBestFit(fillRect, rect, allowedFills))
+ return rect;
+ }
+
+ // X Lines
+ for (int i = x; i <= x2; i++)
+ {
+ Rect rect = new Rect(i, y - depth, GOPHER_SIZE, GOPHER_SIZE);
+ if (rect.CountIn(map) != expectedCount)
+ continue;
+ if (!IsValidForBestFit(fillRect, rect, allowedFills))
+ break;
+ return rect;
+ }
+ for (int i = x; i <= x2; i++)
+ {
+ Rect rect = new Rect(i, y2 - depth, GOPHER_SIZE, GOPHER_SIZE);
+ if (rect.CountIn(map) != expectedCount)
+ continue;
+ if (!IsValidForBestFit(fillRect, rect, allowedFills))
+ break;
+ return rect;
+ }
+
+ // Y Lines
+ for (int i = y; i <= y2; i++)
+ {
+ Rect rect = new Rect(x - depth, i, GOPHER_SIZE, GOPHER_SIZE);
+ if (rect.CountIn(map) != expectedCount)
+ continue;
+ if (!IsValidForBestFit(fillRect, rect, allowedFills))
+ break;
+ return rect;
+ }
+ for (int i = y; i <= y2; i++)
+ {
+ Rect rect = new Rect(x2 - depth, i, GOPHER_SIZE, GOPHER_SIZE);
+ if (rect.CountIn(map) != expectedCount)
+ continue;
+ if (!IsValidForBestFit(fillRect, rect, allowedFills))
+ break;
+ return rect;
+ }
+ }
+
+ return null;
+ }
+
+ private Rect FindBest(Rect fillRect, int expectedCount)
+ {
+ int x = fillRect.X;
+ int y = fillRect.Y;
+ int x2 = fillRect.X2 - GOPHER_SIZE + 1;
+ int y2 = fillRect.Y2 - GOPHER_SIZE + 1;
+
+ // X Lines
+ for (int i = x; i <= x2; i++)
+ for (int j = y; j <= y2; j++)
+ {
+ Rect rect = new Rect(i, j, GOPHER_SIZE, GOPHER_SIZE);
+ if (rect.CountIn(map) != expectedCount)
+ continue;
+ return rect;
+ }
+
+ return null;
+ }
+
+ protected void SolveAndWrite(int problemIndex, TextReader reader, TextWriter writer)
+ {
+ const int GOPHER_AREA = GOPHER_SIZE * GOPHER_SIZE;
+
+ map = new int[MAX_SIZE, MAX_SIZE];
+ allowedFills = GetAllowedFills(A);
+ deployCount = 0;
+
+ Rect fillRect = new Rect(MAX_SIZE / 2 - 1, MAX_SIZE / 2 - 1, GOPHER_SIZE, GOPHER_SIZE);
+ {
+ int[] r = Deploy(reader, writer, fillRect.MidX, fillRect.MidY);
+ map[r[0], r[1]] = 1;
+ }
+ while (fillRect.Area < A)
+ {
+ // Find the best way to increase the search area.
+ Rect best = null;
+ for (int expectedCount = 0; expectedCount < GOPHER_AREA; expectedCount++)
+ {
+ best = FindBestExt(fillRect, expectedCount);
+ if (best != null)
+ break;
+ }
+
+ int[] r = Deploy(reader, writer, best.MidX, best.MidY);
+ if (IsDoneOrError(r))
+ return;
+ int rx = r[0];
+ int ry = r[1];
+ map[rx, ry] = 1;
+ fillRect = fillRect.GrowToInclude(rx, ry);
+ }
+
+ while (true)
+ {
+ Rect best = null;
+ for (int expectedCount = 0; expectedCount < GOPHER_AREA; expectedCount++)
+ {
+ best = FindBest(fillRect, expectedCount);
+ if (best != null)
+ break;
+ }
+
+ if (best == null)
+ break;
+
+ int[] r = Deploy(reader, writer, best.MidX, best.MidY);
+ if (IsDoneOrError(r))
+ return;
+ map[r[0], r[1]] = 1;
+ }
+ }
+
+ private bool IsDoneOrError(int[] r)
+ {
+ if (deployCount >= 1000)
+ return true;
+ return r[0] <= 0 && r[1] <= 0;
+ }
+
+ private int[] Deploy(TextReader reader, TextWriter writer, int x, int y)
+ {
+ deployCount++;
+ writer.WriteLine(x + " " + y);
+ writer.Flush();
+ int[] result = Helper.ParseInts(reader.ReadLine());
+
+ // Fake the read for testing:
+ //int[] result = new int[] { x + rand.Next(3) - 1, y + rand.Next(3) - 1 };
+ return result;
+ }
+
+ protected void ReadInput(TextReader reader)
+ {
+ A = Helper.ParseInt(reader.ReadLine());
+ }
+
+ public void Run()
+ {
+ TextReader reader = null;
+ TextWriter writer = null;
+ try
+ {
+ //reader = new StreamReader("input.txt");
+ //writer = new StreamWriter("output.txt");
+ reader = Console.In;
+ writer = Console.Out;
+
+ int problemCount = Helper.ParseInt(reader.ReadLine());
+ for (int problemIndex = 1; problemIndex <= problemCount; problemIndex++)
+ {
+ ReadInput(reader);
+ SolveAndWrite(problemIndex, reader, writer);
+ }
+ }
+ catch (Exception e)
+ {
+ String msg = "Exception: " + e;
+ Console.Error.WriteLine(msg);
+ Debug.Fail(msg);
+ }
+ finally
+ {
+ if (reader != null)
+ reader.Dispose();
+ if (writer != null)
+ writer.Dispose();
+ }
+ }
+ }
+
+ public class Helper
+ {
+ ///
+ /// Run one problem at a time.
+ /// Just initialize the solver with the correct one.
+ ///
+ public static void Main(string[] args)
+ {
+ GCJ2018_Problem instance = new GCJ2018_Problem();
+ instance.Run();
+ }
+
+ public static int ParseInt(string value)
+ {
+ return Int32.Parse(value, formatProvider);
+ }
+
+ public static int[] ParseInts(string line)
+ {
+ string[] parts = line.Split(' ');
+ int[] result = new int[parts.Length];
+ for (int i = 0; i < parts.Length; i++)
+ {
+ result[i] = ParseInt(parts[i]);
+ }
+ return result;
+ }
+
+ private static readonly IFormatProvider formatProvider = CultureInfo.InvariantCulture;
+ }
+
+ public enum HeapType
+ {
+ Max,
+ Min
+ }
+
+ public sealed class Heap where T : IComparable
+ {
+ internal delegate bool IndexComparor(int childIx, int parentIx);
+ internal IndexComparor IsHigherPriorityThanParent;
+
+ ///
+ /// Constructs a new max heap.
+ ///
+ public Heap() : this(HeapType.Max) { }
+
+ ///
+ /// Constructs a new heap with the given type, allowing you to specify if this heap will be a min or a max heap.
+ ///
+ ///
+ public Heap(HeapType type)
+ {
+ this.List = new List();
+ this.Init(type);
+ }
+
+ ///
+ /// Constructs a new heap with the given type and initial capacity.
+ ///
+ /// The type of heap that determines if it will be a min or max heap.
+ /// The initial capacity of the heap.
+ public Heap(HeapType type, int capacity)
+ {
+ this.List = new List(capacity);
+ this.Init(type);
+ }
+
+ ///
+ /// Initializes some properties of the tree
+ ///
+ ///
+ private void Init(HeapType type)
+ {
+ this.Type = type;
+
+ if (type == HeapType.Max)
+ this.IsHigherPriorityThanParent = this.IsLargerThan;
+ else
+ this.IsHigherPriorityThanParent = this.IsSmallerThanParent;
+ }
+
+ ///
+ /// Identifies the heap as either being a max heap or a min heap
+ ///
+ public HeapType Type { get; private set; }
+
+ internal List List { get; set; }
+
+ ///
+ /// Returns the number of items in the heap
+ ///
+ public int Count { get { return this.List.Count; } }
+
+ ///
+ /// Given an index of a node, this method returns the index of that node's parent
+ ///
+ internal static int ParentIndexOf(int ix)
+ {
+ if (ix == 0)
+ throw new InvalidOperationException("ParentOfRootDoesntExist");
+ else
+ {
+ return (int)Math.Floor((double)(ix - 1) / 2);
+ }
+ }
+
+ ///
+ /// Given an index of a node, this method returns the index of that node's left child
+ ///
+ internal static int LeftChildIndexOf(int ix)
+ {
+ return (2 * ix) + 1;
+ }
+
+ ///
+ /// Given an index of a node, this method returns the index of that node's right child
+ ///
+ internal static int RightChildIndexOf(int ix)
+ {
+ return (2 * ix) + 2;
+ }
+
+ ///
+ /// Returns true if the value of the node at the first index is larger than the value of the node at the second index.
+ ///
+ /// The index of the first value
+ /// The index of the second value
+ internal bool IsLargerThan(int first, int second)
+ {
+ return this.List[first].CompareTo(this.List[second]) > 0;
+ }
+
+ ///
+ /// Returns true if the value of the node at the first index is smaller than the value of the node at the second index.
+ ///
+ /// The index of the first value
+ /// The index of the second value
+ internal bool IsSmallerThanParent(int first, int second)
+ {
+ return this.List[first].CompareTo(this.List[second]) < 0;
+ }
+
+ ///
+ /// Swaps the value at index ix1 with the value at index ix2
+ ///
+ internal void Swap(int ix1, int ix2)
+ {
+ T temp = this.List[ix1];
+ this.List[ix1] = this.List[ix2];
+ this.List[ix2] = temp;
+ }
+
+ ///
+ /// Inserts the given value into the heap, maintaining the heap property as defined by Heap.HeapType
+ ///
+ public void Insert(T value)
+ {
+ int insertedAtIndex = this.List.Count;
+ this.List.Add(value);
+ this.HeapifyUp(insertedAtIndex);
+ }
+
+ ///
+ /// Helper function that takes the node inserted at insertedIx and makes sure it is bubbled up to the correct place in the heap.
+ ///
+ internal void HeapifyUp(int insertedIx)
+ {
+ int currentIx = insertedIx;
+
+ while (currentIx > 0)
+ {
+ int parentIx = ParentIndexOf(currentIx);
+ if (this.IsHigherPriorityThanParent(currentIx, parentIx))
+ this.Swap(currentIx, parentIx);
+ else
+ break;
+
+ currentIx = parentIx;
+ }
+ }
+
+ ///
+ /// Removes the node at the top of the heap and returns its value.
+ ///
+ /// The largest node in the heap if the HeapType = Max, the smallest node in the heap if the HeapType = Min
+ public T Remove()
+ {
+ int lastIx = this.List.Count - 1;
+ T result = default(T);
+ if (lastIx < 0)
+ throw new InvalidOperationException("Cannot remove from empty heap");
+ else
+ {
+ result = this.List[0];
+
+ if (lastIx > 0)
+ this.List[0] = this.List[lastIx];
+
+ this.List.RemoveAt(lastIx);
+ this.HeapifyDown();
+ }
+
+ return result;
+ }
+
+ ///
+ /// Starting at the top of the heap, examines all nodes underneath it ensuring that the heap property is maintained at all nodes.
+ ///
+ internal void HeapifyDown()
+ {
+ int parentIx = 0;
+ while (parentIx < this.Count)
+ {
+ int leftIx = LeftChildIndexOf(parentIx);
+ int rightIx = RightChildIndexOf(parentIx);
+ int largest = parentIx;
+
+ if (leftIx < this.Count && this.IsHigherPriorityThanParent(leftIx, largest))
+ largest = leftIx;
+
+ if (rightIx < this.Count && this.IsHigherPriorityThanParent(rightIx, largest))
+ largest = rightIx;
+
+ if (largest != parentIx)
+ {
+ this.Swap(largest, parentIx);
+ parentIx = largest;
+ }
+ else
+ break;
+ }
+ }
+
+ ///
+ /// Returns the value of the node at the top of the heap without removing it.
+ ///
+ public T Peek()
+ {
+ if (this.List.Count > 0)
+ return this.List[0];
+ else
+ throw new InvalidOperationException("Empty heap");
+ }
+ }
+}
diff --git a/GCJ2018_Qual_SavingThe UniverseAgain.cs b/GCJ2018_Qual_SavingThe UniverseAgain.cs
new file mode 100644
index 0000000..36f1862
--- /dev/null
+++ b/GCJ2018_Qual_SavingThe UniverseAgain.cs
@@ -0,0 +1,366 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+
+namespace Contest
+{
+ public class GCJ2018_Problem
+ {
+ private int shield;
+ private char[] instructions;
+ private int n;
+
+ private bool Hack()
+ {
+ int n = instructions.Length;
+ for (int i = 0; i < n - 1; i++)
+ {
+ if (instructions[i] == 'C' && instructions[i] != instructions[i + 1])
+ {
+ char tmp = instructions[i];
+ instructions[i] = instructions[i + 1];
+ instructions[i + 1] = tmp;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private int CalcDamage()
+ {
+ int totalDamage = 0;
+
+ int current = 1;
+ for (int i = 0; i < n; i++)
+ {
+ if (instructions[i] == 'S')
+ {
+ totalDamage += current;
+ }
+ else
+ {
+ current = current << 1;
+ }
+ }
+ return totalDamage;
+ }
+
+ protected void SolveAndWrite(int problemIndex, TextWriter writer)
+ {
+ int hacks = 0;
+
+ int damage = CalcDamage();
+ while (damage > shield)
+ {
+ bool hacked = Hack();
+ if (!hacked)
+ {
+ break;
+ }
+ hacks++;
+ damage = CalcDamage();
+ }
+
+ if (damage > shield)
+ {
+ writer.Write("IMPOSSIBLE");
+ }
+ else
+ {
+ writer.Write(hacks);
+ }
+ }
+
+ protected void ReadInput(TextReader reader)
+ {
+ String[] parts = reader.ReadLine().Split(' ');
+ shield = Helper.ParseInt(parts[0]);
+ instructions = parts[1].ToCharArray();
+ n = instructions.Length;
+ }
+
+ public void Run()
+ {
+ TextReader reader = null;
+ TextWriter writer = null;
+ try
+ {
+ //reader = new StreamReader("input.txt");
+ //writer = new StreamWriter("output.txt");
+ reader = Console.In;
+ writer = Console.Out;
+
+ int problemCount = Helper.ParseInt(reader.ReadLine());
+ for (int problemIndex = 1; problemIndex <= problemCount; problemIndex++)
+ {
+ ReadInput(reader);
+ writer.Write("Case #{0}: ", problemIndex);
+ SolveAndWrite(problemIndex, writer);
+ writer.WriteLine();
+ }
+ }
+ catch (Exception e)
+ {
+ String msg = "Exception: " + e;
+ Console.WriteLine(msg);
+ Debug.Fail(msg);
+ }
+ finally
+ {
+ if (reader != null)
+ reader.Dispose();
+ if (writer != null)
+ writer.Dispose();
+ }
+ }
+ }
+
+ public class Helper
+ {
+ ///
+ /// Run one problem at a time.
+ /// Just initialize the solver with the correct one.
+ ///
+ public static void Main(string[] args)
+ {
+ GCJ2018_Problem instance = new GCJ2018_Problem();
+ instance.Run();
+ }
+
+ public static int ParseInt(string value)
+ {
+ return Int32.Parse(value, formatProvider);
+ }
+
+ public static int[] ParseInts(string line)
+ {
+ string[] parts = line.Split(' ');
+ int[] result = new int[parts.Length];
+ for (int i = 0; i < parts.Length; i++)
+ {
+ result[i] = ParseInt(parts[i]);
+ }
+ return result;
+ }
+
+ private static readonly IFormatProvider formatProvider = CultureInfo.InvariantCulture;
+ }
+
+ public enum HeapType
+ {
+ Max,
+ Min
+ }
+
+ public sealed class Heap where T : IComparable
+ {
+ internal delegate bool IndexComparor(int childIx, int parentIx);
+ internal IndexComparor IsHigherPriorityThanParent;
+
+ ///
+ /// Constructs a new max heap.
+ ///
+ public Heap() : this(HeapType.Max) { }
+
+ ///
+ /// Constructs a new heap with the given type, allowing you to specify if this heap will be a min or a max heap.
+ ///
+ ///
+ public Heap(HeapType type)
+ {
+ this.List = new List();
+ this.Init(type);
+ }
+
+ ///
+ /// Constructs a new heap with the given type and initial capacity.
+ ///
+ /// The type of heap that determines if it will be a min or max heap.
+ /// The initial capacity of the heap.
+ public Heap(HeapType type, int capacity)
+ {
+ this.List = new List(capacity);
+ this.Init(type);
+ }
+
+ ///
+ /// Initializes some properties of the tree
+ ///
+ ///
+ private void Init(HeapType type)
+ {
+ this.Type = type;
+
+ if (type == HeapType.Max)
+ this.IsHigherPriorityThanParent = this.IsLargerThan;
+ else
+ this.IsHigherPriorityThanParent = this.IsSmallerThanParent;
+ }
+
+ ///
+ /// Identifies the heap as either being a max heap or a min heap
+ ///
+ public HeapType Type { get; private set; }
+
+ internal List List { get; set; }
+
+ ///
+ /// Returns the number of items in the heap
+ ///
+ public int Count { get { return this.List.Count; } }
+
+ ///
+ /// Given an index of a node, this method returns the index of that node's parent
+ ///
+ internal static int ParentIndexOf(int ix)
+ {
+ if (ix == 0)
+ throw new InvalidOperationException("ParentOfRootDoesntExist");
+ else
+ {
+ return (int)Math.Floor((double)(ix - 1) / 2);
+ }
+ }
+
+ ///
+ /// Given an index of a node, this method returns the index of that node's left child
+ ///
+ internal static int LeftChildIndexOf(int ix)
+ {
+ return (2 * ix) + 1;
+ }
+
+ ///
+ /// Given an index of a node, this method returns the index of that node's right child
+ ///
+ internal static int RightChildIndexOf(int ix)
+ {
+ return (2 * ix) + 2;
+ }
+
+ ///
+ /// Returns true if the value of the node at the first index is larger than the value of the node at the second index.
+ ///
+ /// The index of the first value
+ /// The index of the second value
+ internal bool IsLargerThan(int first, int second)
+ {
+ return this.List[first].CompareTo(this.List[second]) > 0;
+ }
+
+ ///
+ /// Returns true if the value of the node at the first index is smaller than the value of the node at the second index.
+ ///
+ /// The index of the first value
+ /// The index of the second value
+ internal bool IsSmallerThanParent(int first, int second)
+ {
+ return this.List[first].CompareTo(this.List[second]) < 0;
+ }
+
+ ///
+ /// Swaps the value at index ix1 with the value at index ix2
+ ///
+ internal void Swap(int ix1, int ix2)
+ {
+ T temp = this.List[ix1];
+ this.List[ix1] = this.List[ix2];
+ this.List[ix2] = temp;
+ }
+
+ ///
+ /// Inserts the given value into the heap, maintaining the heap property as defined by Heap.HeapType
+ ///
+ public void Insert(T value)
+ {
+ int insertedAtIndex = this.List.Count;
+ this.List.Add(value);
+ this.HeapifyUp(insertedAtIndex);
+ }
+
+ ///
+ /// Helper function that takes the node inserted at insertedIx and makes sure it is bubbled up to the correct place in the heap.
+ ///
+ internal void HeapifyUp(int insertedIx)
+ {
+ int currentIx = insertedIx;
+
+ while (currentIx > 0)
+ {
+ int parentIx = ParentIndexOf(currentIx);
+ if (this.IsHigherPriorityThanParent(currentIx, parentIx))
+ this.Swap(currentIx, parentIx);
+ else
+ break;
+
+ currentIx = parentIx;
+ }
+ }
+
+ ///
+ /// Removes the node at the top of the heap and returns its value.
+ ///
+ /// The largest node in the heap if the HeapType = Max, the smallest node in the heap if the HeapType = Min
+ public T Remove()
+ {
+ int lastIx = this.List.Count - 1;
+ T result = default(T);
+ if (lastIx < 0)
+ throw new InvalidOperationException("Cannot remove from empty heap");
+ else
+ {
+ result = this.List[0];
+
+ if (lastIx > 0)
+ this.List[0] = this.List[lastIx];
+
+ this.List.RemoveAt(lastIx);
+ this.HeapifyDown();
+ }
+
+ return result;
+ }
+
+ ///
+ /// Starting at the top of the heap, examines all nodes underneath it ensuring that the heap property is maintained at all nodes.
+ ///
+ internal void HeapifyDown()
+ {
+ int parentIx = 0;
+ while (parentIx < this.Count)
+ {
+ int leftIx = LeftChildIndexOf(parentIx);
+ int rightIx = RightChildIndexOf(parentIx);
+ int largest = parentIx;
+
+ if (leftIx < this.Count && this.IsHigherPriorityThanParent(leftIx, largest))
+ largest = leftIx;
+
+ if (rightIx < this.Count && this.IsHigherPriorityThanParent(rightIx, largest))
+ largest = rightIx;
+
+ if (largest != parentIx)
+ {
+ this.Swap(largest, parentIx);
+ parentIx = largest;
+ }
+ else
+ break;
+ }
+ }
+
+ ///
+ /// Returns the value of the node at the top of the heap without removing it.
+ ///
+ public T Peek()
+ {
+ if (this.List.Count > 0)
+ return this.List[0];
+ else
+ throw new InvalidOperationException("Empty heap");
+ }
+ }
+}
diff --git a/GCJ2018_Qual_TroubleSort.cs b/GCJ2018_Qual_TroubleSort.cs
new file mode 100644
index 0000000..8c85cf1
--- /dev/null
+++ b/GCJ2018_Qual_TroubleSort.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+
+namespace Contest
+{
+ ///
+ /// TODO: optimization for the big input
+ ///
+ public class GCJ2018_Problem
+ {
+ private int[] v;
+ private int n;
+
+ private void TroubleSort()
+ {
+ bool done = false;
+ while (!done)
+ {
+ done = true;
+ for (int i = 0; i < n - 2; i++)
+ {
+ if (v[i] > v[i + 2])
+ {
+ done = false;
+ int tmp = v[i];
+ v[i] = v[i + 2];
+ v[i + 2] = tmp;
+ }
+ }
+ }
+ }
+
+ private int IncorrectIndex()
+ {
+ int failIndex = -1;
+ for (int i = 0; i < n - 1; i++)
+ {
+ if (v[i] > v[i + 1])
+ {
+ failIndex = i;
+ break;
+ }
+ }
+ return failIndex;
+ }
+
+ protected void SolveAndWrite(int problemIndex, TextWriter writer)
+ {
+ TroubleSort();
+ int failIndex = IncorrectIndex();
+
+ if (failIndex >= 0)
+ {
+ writer.Write(failIndex);
+ }
+ else
+ {
+ writer.Write("OK");
+ }
+ }
+
+ protected void ReadInput(TextReader reader)
+ {
+ n = Helper.ParseInt(reader.ReadLine());
+ v = Helper.ParseInts(reader.ReadLine());
+ if (v.Length != n)
+ {
+ throw new InvalidOperationException();
+ }
+ }
+
+ public void Run()
+ {
+ TextReader reader = null;
+ TextWriter writer = null;
+ try
+ {
+ reader = new StreamReader("input.txt");
+ writer = new StreamWriter("output.txt");
+ //reader = Console.In;
+ //writer = Console.Out;
+
+ int problemCount = Helper.ParseInt(reader.ReadLine());
+ for (int problemIndex = 1; problemIndex <= problemCount; problemIndex++)
+ {
+ ReadInput(reader);
+ writer.Write("Case #{0}: ", problemIndex);
+ SolveAndWrite(problemIndex, writer);
+ writer.WriteLine();
+ }
+ }
+ catch (Exception e)
+ {
+ String msg = "Exception: " + e;
+ Console.WriteLine(msg);
+ Debug.Fail(msg);
+ }
+ finally
+ {
+ if (reader != null)
+ reader.Dispose();
+ if (writer != null)
+ writer.Dispose();
+ }
+ }
+ }
+
+ public class Helper
+ {
+ ///
+ /// Run one problem at a time.
+ /// Just initialize the solver with the correct one.
+ ///
+ public static void Main(string[] args)
+ {
+ GCJ2018_Problem instance = new GCJ2018_Problem();
+ instance.Run();
+ }
+
+ public static int ParseInt(string value)
+ {
+ return Int32.Parse(value, formatProvider);
+ }
+
+ public static int[] ParseInts(string line)
+ {
+ string[] parts = line.Split(' ');
+ int[] result = new int[parts.Length];
+ for (int i = 0; i < parts.Length; i++)
+ {
+ result[i] = ParseInt(parts[i]);
+ }
+ return result;
+ }
+
+ private static readonly IFormatProvider formatProvider = CultureInfo.InvariantCulture;
+ }
+}
diff --git a/IProblem.cs b/IProblem.cs
new file mode 100644
index 0000000..84d9f71
--- /dev/null
+++ b/IProblem.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Contest
+{
+ public interface IProblem
+ {
+ void Run();
+ }
+}
diff --git a/Program.cs b/Program.cs
new file mode 100644
index 0000000..0faca03
--- /dev/null
+++ b/Program.cs
@@ -0,0 +1,15 @@
+namespace Contest
+{
+ class Program
+ {
+ ///
+ /// Run one problem at a time.
+ /// Just initialize the solver with the correct one.
+ ///
+ static void Main(string[] args)
+ {
+ IProblem problem = new GCJ2017_B_TidyNumbers();
+ problem.Run();
+ }
+ }
+}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..9a8498f
--- /dev/null
+++ b/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Contest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Contest")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("14c05281-a66c-45a1-8de5-a0c869489557")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/input.txt b/input.txt
new file mode 100644
index 0000000..0578357
--- /dev/null
+++ b/input.txt
@@ -0,0 +1,5 @@
+2
+5
+5 6 8 4 3
+3
+8 9 7
\ No newline at end of file
diff --git a/input_small.txt b/input_small.txt
new file mode 100644
index 0000000..c467390
--- /dev/null
+++ b/input_small.txt
@@ -0,0 +1,101 @@
+100
+---+-++- 3
++++++ 4
+-+-+- 4
++++ 3
+-+++- 3
+++--+-+-- 3
+++++ 3
+-++- 2
+--- 2
+-+-+ 3
++-+- 3
++-+ 3
+--+- 3
+++- 3
+---------- 10
++-++++-++ 5
+--- 3
+-- 2
++-++ 3
+---+ 3
+++-+ 2
+--------- 3
++++ 2
+++++++++++ 10
+++-+ 3
+-------+-- 10
+-+++ 2
+-+-+-+-+-+ 2
+-+-- 2
+---- 2
+-+- 2
++-+ 2
+--++ 3
+------ 6
++- 2
++--+++--++ 5
++++---- 4
+-+-++ 2
+++-- 3
++--+--++ 5
++-+-+-+-+- 2
+-++++++++- 2
+-+++++++++ 2
++-+- 2
++-- 2
+++----++-- 2
+--+ 2
+++++ 2
+---++-+--- 4
+-+++++++-- 2
++++- 3
++-+-+-+-+- 3
+-++++- 5
+-+-- 3
+-----+ 5
+-+-+ 2
+-++ 3
+---+ 2
++--- 2
+++ 2
+---++ 3
+-+++++++-+ 2
+-++++++++- 9
+--+- 2
+---------- 2
++-+-+-+ 3
++--+ 2
+-++++++++- 8
+--++ 2
+-+- 3
++-++++-+- 5
+++-++ 5
+++++++++- 6
+-++++++++- 10
++--------- 9
++--- 3
+++--+-- 3
+-+++--+ 4
+------++ 6
++++- 2
++-++ 2
+++-- 2
++--+ 3
+--+ 3
++-- 3
+++- 2
+---------- 3
+++-------- 8
+++-++--+-- 2
+-+++ 3
+-++- 3
++++++++++ 8
+--------+ 8
+---------- 5
+------- 4
++-+-+-+- 3
+-+ 2
+-++ 2
+---- 3
++-+-+-+-+ 3
diff --git a/output.txt b/output.txt
new file mode 100644
index 0000000..586d708
--- /dev/null
+++ b/output.txt
@@ -0,0 +1,2 @@
+Case #1: OK
+Case #2: 1
diff --git a/qr2017_a_oversized_pancake_flipper.cpp b/qr2017_a_oversized_pancake_flipper.cpp
new file mode 100644
index 0000000..2e728e3
--- /dev/null
+++ b/qr2017_a_oversized_pancake_flipper.cpp
@@ -0,0 +1,128 @@
+// -------------------------------------
+// STATUS:
+// <>
+// -------------------------------------
+#ifdef WIN32
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#define _USE_MATH_DEFINES
+#include
+#include
+#include
+#include