Skip to content

Commit 4f89d6a

Browse files
authored
Create 564-find-the-closest-palindrome.js
1 parent ae3dedb commit 4f89d6a

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed

564-find-the-closest-palindrome.js

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/**
2+
* @param {bigint | string} n
3+
* @return {string}
4+
*/
5+
const nearestPalindromic = function(n) {
6+
let bigInt = null
7+
8+
if (typeof n === 'bigint') bigInt = n
9+
if (typeof n === 'string') bigInt = BigInt(n)
10+
if (typeof n == null) throw new Error('unknown input type')
11+
12+
// take the number, keep adding 1 to it, then check if it's a palindrome
13+
const prevPalindrome = getPrevPalindrome(bigInt)
14+
const nextPalindrome = getNextPalindrome(bigInt)
15+
16+
const scalarPrev = bigInt - prevPalindrome
17+
const scalarNext = nextPalindrome - bigInt
18+
19+
if (scalarPrev <= scalarNext) return prevPalindrome.toString()
20+
else return nextPalindrome.toString()
21+
}
22+
23+
/**
24+
*
25+
* @param {bigint} number
26+
*/
27+
function getPrevPalindrome(number) {
28+
const decrementedNumber =
29+
typeof number === 'bigint' ? number - BigInt(1) : BigInt(number) - BigInt(1)
30+
31+
if (decrementedNumber.toString().length === 1) return decrementedNumber
32+
33+
const leftSide = getLeftSideNumber(decrementedNumber)
34+
const palindromedLeft = getPalindromeAsString(leftSide)
35+
36+
const rightSide = getRightSideNumberAsString(decrementedNumber)
37+
const comparison = compareTwoValues(BigInt(palindromedLeft), BigInt(rightSide))
38+
if (comparison === 0) {
39+
// the right side is already the palindromedLeft - return the incrementedNumber
40+
return decrementedNumber
41+
}
42+
if (comparison === 1) {
43+
// this means the right side is already too far advanced (going downwards) compared to the palindromedLeft,
44+
// you need to take the leftSideWithBorder, decrement by 1, then return this new number concatenated with
45+
// the leftSide's palindrome - this is the answer
46+
const leftWithBorder = getLeftSideNumberWithBorder(decrementedNumber)
47+
const decremented = leftWithBorder - BigInt(1)
48+
49+
if (decremented === BigInt(0)) return BigInt(9)
50+
51+
const newWhole = BigInt(decremented.toString() + getRightSideNumberAsString(decrementedNumber))
52+
53+
const newLeft = getLeftSideNumber(newWhole)
54+
const palindromedNewLeft = getPalindromeAsString(newLeft)
55+
return BigInt(decremented.toString() + palindromedNewLeft.toString())
56+
}
57+
if (comparison === -1) {
58+
// this means the right side can naturally increment to the palindromedLeft,
59+
// so you can just return the leftSideWithBorder concatenated with the palindromedLeft
60+
const leftSideWithBorder = getLeftSideNumberWithBorder(decrementedNumber)
61+
return BigInt(leftSideWithBorder.toString() + palindromedLeft)
62+
}
63+
}
64+
65+
/**
66+
*
67+
* @param {bigint} number
68+
* @returns {*}
69+
*/
70+
function getNextPalindrome(number) {
71+
const incrementedNumber =
72+
typeof number === 'bigint' ? number + BigInt(1) : BigInt(number) + BigInt(1)
73+
74+
if (incrementedNumber.toString().length === 1) return incrementedNumber
75+
76+
const leftSide = getLeftSideNumber(incrementedNumber)
77+
const palindromedLeft = getPalindromeAsString(leftSide)
78+
79+
const rightSide = getRightSideNumberAsString(incrementedNumber)
80+
const comparison = compareTwoValues(BigInt(palindromedLeft), BigInt(rightSide))
81+
if (comparison === 0) {
82+
// the right side is already the palindromedLeft - return the incrementedNumber
83+
return incrementedNumber
84+
}
85+
if (comparison === 1) {
86+
// this means the right side can naturally increment to the palindromedLeft,
87+
// so you can just return the leftSideWithBorder concatenated with the palindromedLeft
88+
const leftSideWithBorder = getLeftSideNumberWithBorder(incrementedNumber)
89+
const leftAsString = leftSideWithBorder.toString()
90+
const combined = leftAsString + palindromedLeft
91+
return BigInt(combined)
92+
}
93+
if (comparison === -1) {
94+
// this means the right side is already too far advanced compared to the palindromedLeft,
95+
// you need to take the leftSideWithBorder, increment by 1, then return this new number concatenated with
96+
// the leftSide's palindrome - this is the answer
97+
const leftWithBorder = getLeftSideNumberWithBorder(incrementedNumber)
98+
const incrementedLeftWithBorder = leftWithBorder + BigInt(1)
99+
const newWhole = BigInt(
100+
incrementedLeftWithBorder.toString() + getRightSideNumberAsString(incrementedNumber)
101+
)
102+
103+
const newLeft = getLeftSideNumber(newWhole)
104+
const palindromedNewLeft = getPalindromeAsString(newLeft)
105+
return BigInt(incrementedLeftWithBorder.toString() + palindromedNewLeft.toString())
106+
}
107+
}
108+
109+
/**
110+
*
111+
* @param {bigint} number
112+
*/
113+
function getLeftSideNumber(number) {
114+
const numberAsText = number.toString()
115+
const numCharsInLeftSide = Math.floor(numberAsText.length / 2)
116+
return BigInt(numberAsText.slice(0, numCharsInLeftSide))
117+
}
118+
119+
/**
120+
*
121+
* @param {bigint} number
122+
* @returns {bigint}
123+
*/
124+
function getLeftSideNumberWithBorder(number) {
125+
const numberAsText = number.toString()
126+
const hasOddNumChars = numberAsText.length % 2 === 1
127+
128+
const left = getLeftSideNumber(number)
129+
130+
// should return the left side only, if it's an even-digited number
131+
// else, return the left side together with the border number (since it's an odd-digited number)
132+
if (hasOddNumChars) {
133+
const middleChar = numberAsText.charAt(Math.floor(numberAsText.length / 2))
134+
return BigInt(left.toString() + middleChar)
135+
} else {
136+
return BigInt(left.toString())
137+
}
138+
}
139+
140+
/**
141+
*
142+
* @param {bigint} number
143+
* @returns {string}
144+
*/
145+
function getRightSideNumberAsString(number) {
146+
const numberAsText = number.toString()
147+
const numCharsInRightSide = Math.floor(numberAsText.length / 2)
148+
return numberAsText.slice(numberAsText.length - numCharsInRightSide)
149+
}
150+
151+
/**
152+
*
153+
* @param {bigint} number
154+
* @returns {string}
155+
*/
156+
function getPalindromeAsString(number) {
157+
const numberAsText = number.toString()
158+
return numberAsText
159+
.split('')
160+
.reverse()
161+
.join('')
162+
}
163+
164+
/**
165+
*
166+
* @param {bigint} number1
167+
* @param {bigint} number2
168+
* @returns {number}
169+
*/
170+
function compareTwoValues(number1, number2) {
171+
if (number1 < number2) return -1
172+
if (number1 === number2) return 0
173+
if (number1 > number2) return 1
174+
}

0 commit comments

Comments
 (0)