diff options
| -rw-r--r-- | 2025/09/b-fixed.py | 48 | ||||
| -rw-r--r-- | 2025/README.md | 25 |
2 files changed, 73 insertions, 0 deletions
diff --git a/2025/09/b-fixed.py b/2025/09/b-fixed.py new file mode 100644 index 0000000..eedc275 --- /dev/null +++ b/2025/09/b-fixed.py | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | import fileinput | ||
| 2 | |||
| 3 | with fileinput.input() as lines: | ||
| 4 | a = [tuple(int(x) for x in l[:-1].split(',')) for l in lines] | ||
| 5 | |||
| 6 | # Check if the border is turning clockwise or counter-clockwise | ||
| 7 | def dir(p, q): | ||
| 8 | return p[0]*q[1]-p[1]*q[0] | ||
| 9 | t = 0 | ||
| 10 | for i in range(len(a)): | ||
| 11 | p, q, r = a[i%len(a)], a[(i+1)%len(a)], a[(i+2)%len(a)] | ||
| 12 | t += 1 if dir((q[0]-p[0],q[1]-p[1]), (r[0]-q[0],r[1]-q[1])) > 0 else -1 | ||
| 13 | |||
| 14 | def external_by_vertex(a, i, j): | ||
| 15 | p = tuple(a[(i+1)%len(a)][k] - a[i][k] for k in range(2)) | ||
| 16 | q = tuple(a[j][k] - a[i][k] for k in range(2)) | ||
| 17 | |||
| 18 | return t * dir(p, q) < 0 | ||
| 19 | |||
| 20 | def lbreaks(p, q, tl, br): | ||
| 21 | # Adjust for horizontal or vertical | ||
| 22 | (tt, z) = (t, 0) if p[0] == q[0] else (-t, 1) | ||
| 23 | |||
| 24 | if min(p[1-z], q[1-z]) >= br[1-z] or max(p[1-z], q[1-z]) <= tl[1-z]: | ||
| 25 | return False | ||
| 26 | if p[z] == tl[z]: | ||
| 27 | return tt * (q[1-z]-p[1-z]) > 0 | ||
| 28 | if p[z] == br[z]: | ||
| 29 | return tt * (q[1-z]-p[1-z]) < 0 | ||
| 30 | |||
| 31 | return p[z] > tl[z] and p[z] < br[z] | ||
| 32 | |||
| 33 | def admissible(a, i, j): | ||
| 34 | # Fix (see ../README.md): check given vertices to determine if the | ||
| 35 | # rectangle is fully external to the figure. | ||
| 36 | if external_by_vertex(a, i, j): | ||
| 37 | return False | ||
| 38 | |||
| 39 | tl = (min(a[i][0], a[j][0]), min(a[i][1], a[j][1])) | ||
| 40 | br = (max(a[i][0], a[j][0]), max(a[i][1], a[j][1])) | ||
| 41 | return not any(lbreaks(a[k], a[(k+1)%len(a)], tl, br) for k in range(len(a))) | ||
| 42 | |||
| 43 | s = 0 | ||
| 44 | for i in range(len(a)): | ||
| 45 | for j in range(i+1, len(a)): | ||
| 46 | if admissible(a, i, j): | ||
| 47 | s = max(s, (abs(a[i][0]-a[j][0])+1)*(abs(a[i][1]-a[j][1])+1)) | ||
| 48 | print(s) | ||
diff --git a/2025/README.md b/2025/README.md index c1d3f2c..d75a4d3 100644 --- a/2025/README.md +++ b/2025/README.md | |||
| @@ -148,3 +148,28 @@ and in fact I wasted a lot of time searching a quadratic or O(n^2log n) | |||
| 148 | solution before I focused on formalizing a cubic one. The problem is that | 148 | solution before I focused on formalizing a cubic one. The problem is that |
| 149 | I did not have smaller inputs to try my code against, so I this solution | 149 | I did not have smaller inputs to try my code against, so I this solution |
| 150 | was too slow I did not have any way to check that it was at least correct. | 150 | was too slow I did not have any way to check that it was at least correct. |
| 151 | |||
| 152 | EDIT (about 12h after solving part 2): apparently my algorithm is not | ||
| 153 | entirely correct. In particular, it can fail by selecting a rectangle | ||
| 154 | that is completely external to the figure and none of whose sides overlaps | ||
| 155 | any of the lines. | ||
| 156 | |||
| 157 | For example with this input: | ||
| 158 | |||
| 159 | ``` | ||
| 160 | 101,51 | ||
| 161 | 101,0 | ||
| 162 | 0,0 | ||
| 163 | 0,2 | ||
| 164 | 1,2 | ||
| 165 | 1,1 | ||
| 166 | 100,1 | ||
| 167 | 100,50 | ||
| 168 | 99,50 | ||
| 169 | 99,51 | ||
| 170 | 101,51 | ||
| 171 | ``` | ||
| 172 | |||
| 173 | The first version of my program return 4851 instead of 202. I added a | ||
| 174 | check for this case in `b-fixed.py`, hopefully it works in 100% of the | ||
| 175 | cases now. | ||
