1
+ # https://codingcompetitions.withgoogle.com/codejam/round/0000000000c95433/0000000000cad339
2
+ # Game Sort: Part 2
3
+ from collections import defaultdict
4
+ T = int (input ())
5
+ def solve_for_counts (frontcount , backcount ):
6
+ frontsmall = min (k for k in frontcount if frontcount [k ]> 0 )
7
+ backbig = max (k for k in backcount if backcount [k ] > 0 )
8
+ if frontsmall > backbig :
9
+ return True
10
+ if frontsmall == backbig :
11
+ if len ([k for k in frontcount if frontcount [k ] > 0 ]) > 1 :
12
+ return True
13
+ if frontcount [frontsmall ] > backcount [backbig ]:
14
+ return True
15
+ return False
16
+
17
+ def solve_for_two (p , s , backcount ):
18
+ if len (backcount ) == 1 :
19
+ if len (s ) == 2 :
20
+ return None
21
+ else :
22
+ return (s [:- 1 ], s [- 1 ])
23
+ frontcount = defaultdict (int )
24
+ for i in range (1 , len (s )):
25
+ frontcount [s [i - 1 ]] += 1
26
+ backcount [s [i - 1 ]] -= 1
27
+ if solve_for_counts (frontcount , backcount ):
28
+ return (s [:i ], s [i :])
29
+ return None
30
+
31
+ def fil (d ):
32
+ return [k for k in d if d [k ] > 0 ]
33
+
34
+ def solve (p ,s ):
35
+ # return True if Amir wins
36
+ lettercount = defaultdict (int )
37
+ for x in s :
38
+ lettercount [x ] += 1
39
+ if p == 2 :
40
+ # Amir generally loses
41
+ # 1. if there's some point where every letter in A >= B
42
+ # then Amir wins, unless A only contains some letter
43
+ # and B has more of that letter.
44
+ # 2. if all the letters are the same, then Amir wins
45
+ # (as long as |S| > 2)
46
+ return solve_for_two (p ,s ,lettercount )
47
+ elif p == 3 :
48
+ # this one is hard
49
+ # brute force?
50
+ # is there some A,B,C where
51
+ # A<B is possible and B<C is possible
52
+ # but A<B<C is impossible?
53
+ # for example, ac | ab | b
54
+
55
+ # efficiently, we could iterate through i
56
+ # where A = s[:i] and B = s[i:j] where j is s.t.
57
+ # B is small as possible... which is just j=i+1 actually.
58
+ # Then we can iterate through all j where B=s[i:j] and C=s[j:]
59
+ # to efficiently find s[i:j] that forces B to be biggest possible
60
+ # maybe with sliding window: you only expand the window
61
+ # if s[i] >= argmax(s[i+1:j])
62
+
63
+ # first, check any splits where A>B
64
+ frontcount = defaultdict (int )
65
+ for i in range (1 , len (s )- 1 ):
66
+ frontcount [s [i - 1 ]] += 1
67
+ if solve_for_counts (frontcount , {s [i ]:1 }):
68
+ # print('suces', i)
69
+ return (s [:i ], s [i ], s [i + 1 :])
70
+ # then, do sliding window backwards
71
+ backcount = defaultdict (int )
72
+ midcount = defaultdict (int )
73
+ i = len (s )- 1 #inclusive
74
+ midcount [s [len (s )- 1 ]] += 1
75
+ for j in range (len (s )- 1 - 1 , 0 , - 1 ):
76
+ backcount [s [j + 1 ]] += 1
77
+ midcount [s [j + 1 ]] -= 1
78
+ while i - 1 > 0 and (
79
+ len (fil (midcount )) == 0 or s [i - 1 ]>= max (fil (midcount ))
80
+ ):
81
+ midcount [s [i - 1 ]] += 1
82
+ i -= 1
83
+ if solve_for_counts (midcount , backcount ):
84
+ # print(i,j)
85
+ # print(midcount, backcount)
86
+ return (s [:i ], s [i :j + 1 ], s [j + 1 :])
87
+
88
+ else :
89
+ # Amir generally wins:
90
+ # just take a big letter as a singleton, and later a
91
+ # small letter as a singleton.
92
+ # Amir loses only if the letters are non-increasing
93
+ # and even then, Amir wins if there are 3 of the
94
+ # same letter.
95
+ # What if the letters are non-increasing with less than
96
+ # 3 of each letter? Then Amir loses.
97
+ raise ValueError ('unimplemented but this part is actually really easy' )
98
+
99
+ for t in range (T ):
100
+ p , s = input ().split ()
101
+ p = int (p )
102
+ ans = solve (p ,s )
103
+ print (f"Case #{ t + 1 } : { 'POSSIBLE' if ans is not None else 'IMPOSSIBLE' } " )
104
+ if ans is not None :
105
+ print (' ' .join (ans ))
106
+
0 commit comments