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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +typedef long long ll; +typedef long double ld; + +const int inf = 1 << 30; + +FILE *fin, *fout; + +inline char my_readChar() { char c; do { fscanf(fin, "%c", &c); } while(c == '\r' || c == '\n'); return c; } + +// Add extra defines +#define T 10002 + +int v[T]; +int n, k; +int nFlips; + +void read(int problemIdx) { + int r; + char c; + + n = 0; + k = 0; + while (true) { + r = fscanf(fin, "%c", &c); + if (c == '+') { + v[n] = 1; + } + else if (c == '-') { + v[n] = 0; + } + else { + break; + } + n++; + } + v[n] = 9999; + r = fscanf(fin, "%d\n", &k); + + printf("%d %d\n", n, k); +} + +void flipAsc(int index) { + int end = index + k; + assert(end <= n); + + for (int i = index; i < end; i++) { + v[i] = 1 - v[i]; + } +} + +void solve(int problemIdx) { + nFlips = 0; + for (int i = 0; i < n - k + 1; i++) { + if (v[i] == 0) { + flipAsc(i); + nFlips++; + } + } +} + +void write(int problemIdx) { + int cnt = 0; + for (int i = 0; i < n; i++) { + cnt += v[i]; + } + if (cnt == n) { + fprintf(fout, "%d", nFlips); + } + else { + fprintf(fout, "IMPOSSIBLE"); + } +} + +int main(int argc, char** argv) { + + fin = fopen("input.txt", "rt"); + fout = fopen("output.txt", "wt"); + //FILE *fout = stdout; + + int problemCount; + fscanf(fin, "%d\n", &problemCount); + for (int problemIdx = 1; problemIdx <= problemCount; problemIdx++) { + read(problemIdx); + solve(problemIdx); + fprintf(fout, "Case #%d: ", problemIdx); + write(problemIdx); + if (problemIdx < problemCount) { + fprintf(fout, "\n"); + } + } + + fclose(fin); + fclose(fout); + + return 0; +}