You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: problems/564/jeremymanning.md
+207
Original file line number
Diff line number
Diff line change
@@ -107,3 +107,210 @@ class Solution:
107
107
-`n = "4387348756345786"`: pass
108
108
- `n = "438734878437834": fail! (note: I also had to fix up the "wiggle" code syntax).
109
109
- There seems to be an issue with the `wiggle_middle_digits` code-- it doesn't seem to be working as expected. However, I'm out of time for tonight, so I'll have to come back to this!
110
+
111
+
## Coming back to this...
112
+
- I'm debugging the `wiggle_middle_digits` code, and I notice a few issues:
113
+
- My indexing is off by 1 (the "changing" part should be):
114
+
```python
115
+
iflen(n) %2==0:
116
+
x1[len(n) //2-1] = x1_middle
117
+
x1[len(n) //2] = x1_middle
118
+
x2[len(n) //2-1] = x2_middle
119
+
x2[len(n) //2] = x2_middle
120
+
else:
121
+
x1[len(n) //2] = x1_middle
122
+
x2[len(n) //2] = x2_middle
123
+
```
124
+
- Here's the updated code:
125
+
```python
126
+
from copy import copy
127
+
128
+
classSolution:
129
+
defnearestPalindromic(self, n: str) -> str:
130
+
defis_palindrome(n):
131
+
return n[:len(n) //2] == n[-(len(n) //2):][::-1]
132
+
133
+
defdist(a, b):
134
+
returnabs(int(a) -int(b))
135
+
136
+
defwiggle_middle_digits(n):
137
+
x1 =list(copy(n))
138
+
x2 =list(copy(n))
139
+
140
+
x1_middle =str(int(n[len(n) //2]) -1)
141
+
x2_middle =str(int(n[len(n) //2]) +1)
142
+
143
+
iflen(n) %2==0:
144
+
x1[len(n) //2-1] = x1_middle
145
+
x1[len(n) //2] = x1_middle
146
+
x2[len(n) //2-1] = x2_middle
147
+
x2[len(n) //2] = x2_middle
148
+
else:
149
+
x1[len(n) //2] = x1_middle
150
+
x2[len(n) //2] = x2_middle
151
+
152
+
x1 =''.join(x1)
153
+
x2 =''.join(x2)
154
+
155
+
if dist(n, x1) <= dist(n, x2):
156
+
return x1
157
+
else:
158
+
return x2
159
+
160
+
iflen(n) ==1:
161
+
if n =="0":
162
+
return"1"
163
+
else:
164
+
returnstr(int(n) -1)
165
+
166
+
if is_palindrome(n):
167
+
return wiggle_middle_digits(n)
168
+
eliflen(n) %2==0:
169
+
return n[:len(n)//2] + n[:len(n)//2][::-1]
170
+
else:
171
+
return n[:len(n)//2+1] + n[:len(n)//2][::-1]
172
+
```
173
+
- Now this test case passes.
174
+
- Let's try submitting...
175
+
176
+

177
+
178
+
- Ah. I forgot to account for this case (when `n = "10"` the correct answer should be `"9"`, not `"11"`).
179
+
- In general, there could be a whole range of these sorts of cases (not just when there are only two digits). E.g., when `n = "100000"` we should output `"99999"`.
180
+
- I think we could handle this with one more check: if `is_palindrome(str(int(n) - 1))` then return that:
- Now `n = "10"` and `n = "1000000"` both pass; re-submitting...
233
+
234
+

235
+
236
+
- Oof 🤦. Right...`"00"` isn't a valid output, but the `"1"'s in `"11"` are technically the "middle digits".
237
+
- There are a bunch of these sorts of edge cases. I think we actually need to generate a *set* of candidates, and then pick the closest (or smallest + closest if there's a tie):
238
+
- First try mirroring the left half of the string
239
+
- Also try wiggling the middle digit(s)
240
+
- Check if we're in a "close to a power of 10" scenario. We can just add `"9" * (len(n) - 1)` and `"1" + "0" * (len(n) - 1) + "1"` to the set of candidates manually
241
+
- In case any of these have reproduced the original number, remove it
242
+
- If we have empty strings, all zeros, etc., we'll remove those too
243
+
- Of the remaining candidates, find the closest to `n` that is also the smallest-- we can do this by returning `min(candidates, key=lambda x: (dist(n, x), int(x)))`
244
+
- Updated solution:
245
+
```python
246
+
classSolution:
247
+
defnearestPalindromic(self, n: str) -> str:
248
+
defis_palindrome(x):
249
+
return x == x[::-1]
250
+
251
+
defdist(a, b):
252
+
returnabs(int(a) -int(b))
253
+
254
+
defwiggle_middle_digits(n):
255
+
x1 =list(n)
256
+
x2 =list(n)
257
+
258
+
mid_index =len(n) //2
259
+
iflen(n) %2==0:
260
+
left_part = n[:mid_index]
261
+
x1_middle =str(int(left_part) -1)
262
+
x2_middle =str(int(left_part) +1)
263
+
x1 = x1_middle + x1_middle[::-1]
264
+
x2 = x2_middle + x2_middle[::-1]
265
+
else:
266
+
left_part = n[:mid_index +1]
267
+
x1_middle =str(int(left_part) -1)
268
+
x2_middle =str(int(left_part) +1)
269
+
x1 = x1_middle + x1_middle[:-1][::-1]
270
+
x2 = x2_middle + x2_middle[:-1][::-1]
271
+
272
+
# new special cases (e.g., 999 vs. 1001)
273
+
iflen(x1) <len(n) or x1 =='':
274
+
x1 ="9"* (len(n) -1)
275
+
iflen(x2) >len(n) or x2 =='':
276
+
x2 ="1"+"0"* (len(n) -1) +"1"
277
+
278
+
return (x1, x2)
279
+
280
+
if n =="1":
281
+
return"0"
282
+
283
+
candidates =set()
284
+
285
+
# mirroring
286
+
iflen(n) %2==0:
287
+
mid_index =len(n) //2
288
+
mirrored = n[:mid_index] + n[:mid_index][::-1]
289
+
else:
290
+
mid_index =len(n) //2
291
+
mirrored = n[:mid_index +1] + n[:mid_index][::-1]
292
+
293
+
candidates.add(mirrored)
294
+
295
+
# wiggling
296
+
wiggle_candidates = wiggle_middle_digits(n)
297
+
candidates.add(wiggle_candidates[0])
298
+
candidates.add(wiggle_candidates[1])
299
+
300
+
# edge cases (for when we're "near" a power of 10)
301
+
candidates.add("9"* (len(n) -1))
302
+
candidates.add("1"+"0"* (len(n) -1) +"1")
303
+
304
+
# remove bad candidates (including the original number)
305
+
candidates.discard(n)
306
+
candidates = {c for c in candidates if c and c.isdigit()}
0 commit comments