-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathPALIN.cs
86 lines (76 loc) · 3.03 KB
/
PALIN.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
using System;
using System.Linq;
// https://www.spoj.com/problems/PALIN/ #ad-hoc
// Outputs the smallest palindrome larger than the given integer.
public static class PALIN
{
public static string Solve(string k)
{
// Need to handle even-length and odd-length arrays a bit differently,
// since odds have a middle index.
int? middleIndex = k.Length % 2 == 0 ? (int?)null : k.Length / 2;
int leftHalfStartIndex = middleIndex - 1 ?? k.Length / 2 - 1;
int rightHalfStartIndex = middleIndex + 1 ?? leftHalfStartIndex + 1;
char[] ret;
// Handle the edge case where the integer is all nines; this is the only case
// where it's necessary to add an extra digit to find the smallest larger palindrome.
// To see this, note if it's not all nines then there's at least the all nines
// palindrome larger than it, with the same number of digits.
if (k.All(c => c == '9'))
{
ret = new char[k.Length + 1];
ret[0] = ret[ret.Length - 1] = '1';
for (int i = 1; i < ret.Length - 1; ++i)
{
ret[i] = '0';
}
return new string(ret);
}
// Solve knowing the result has the same number of digits as the input. Only one
// palindrome can be made from the input without increasing the left half of the
// number; by mirroring the left half to the right. That number isn't necessarily
// larger than the input number though.
ret = k.ToCharArray();
for (int l = leftHalfStartIndex, r = rightHalfStartIndex; l >= 0; --l, ++r)
{
if (k[l] > k[r])
{
// The left half mirrored is larger than the right, so the palindrome made from
// the left half mirrored to the right is larger than the input, and hence valid.
for (l = leftHalfStartIndex, r = rightHalfStartIndex; l >= 0; --l, ++r)
{
ret[r] = ret[l];
}
return new string(ret);
}
if (k[l] < k[r])
break;
}
// The left half mirrored isn't larger than the right, so make the left half minimally
// larger so the number as a whole is larger than the input, and then turn it into a palindrome.
for (int l = middleIndex ?? leftHalfStartIndex; l >= 0; --l)
{
bool keepCarryingTheOne = ret[l] == '9';
ret[l] = keepCarryingTheOne ? '0' : (char)(ret[l] + 1);
if (!keepCarryingTheOne)
break;
}
for (int l = leftHalfStartIndex, r = rightHalfStartIndex; l >= 0; --l, ++r)
{
ret[r] = ret[l];
}
return new string(ret);
}
}
public static class Program
{
private static void Main()
{
int remainingTestCases = int.Parse(Console.ReadLine());
while (remainingTestCases-- > 0)
{
Console.WriteLine(
PALIN.Solve(Console.ReadLine()));
}
}
}