diff --git a/.gitignore b/.gitignore index a81f529..c063402 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +venv/ .idea/ *.html *.sqlite diff --git a/contextvar.py b/contextvar.py new file mode 100644 index 0000000..0dfb544 --- /dev/null +++ b/contextvar.py @@ -0,0 +1,37 @@ +import asyncio +from contextvars import ContextVar + +cv = ContextVar("cv") + +async def ff(x): + v = cv.get(666) + print(f"f({x}) -> {v}") + cv.set(11) + +async def f(): + while True: + await ff(" f ") + await asyncio.sleep(1) + +async def gg(x): + v = cv.get(555) + print(f"g({x}) -> {v}") + cv.set(22) + + +async def g(): + while True: + await ff("g") + await gg("g") + await asyncio.sleep(0.4) + +async def main(): + ff = asyncio.create_task(f()) + gg = asyncio.create_task(g()) + #ff = asyncio.Task(f()) + #gg = asyncio.Task(g()) + #await asyncio.gather(ff, gg) + await asyncio.sleep(20) + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/getattr_tests.py b/getattr_tests.py new file mode 100644 index 0000000..300f056 --- /dev/null +++ b/getattr_tests.py @@ -0,0 +1,48 @@ +# I would like to make what I think is called a facade object. Pass all calls except a selected one or two to the +# base object. + +class A: + def f(self): + print("Af") + def __getattr__(self, item): + print(f"item={item}") + +iter(A()) + +hasattr(A(), "__iter__") + + +class B: + def f(self): + print("f") + +b = B() +b.f() + +def g(f): + def ff(): + print("ff-before") + rv = f() + print("ff-after") + return rv + return ff + +b.f = g(b.f) + +class C: + def __init__(self, x): + self._x = x + + def __getattr__(self, name): + return getattr(self._x, name) + +c = C(B()) +c.f() + + +class D(A): + def f(self): + print("df") + super().f() + print("dfafer") +D().f() diff --git a/leetcode/20201227sun/ex.py b/leetcode/20201227sun/ex.py new file mode 100644 index 0000000..bf2ca84 --- /dev/null +++ b/leetcode/20201227sun/ex.py @@ -0,0 +1,312 @@ +import numpy as np +import matplotlib.pyplot as plt +import pandas as pd +import logging +import sys + +log = logging.getLogger() +log.setLevel(logging.INFO) +handler = logging.StreamHandler(sys.stdout) +handler.setLevel(logging.DEBUG) +log.addHandler(handler) + +vow = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'] + + +def alike(s1, s2): + def count_in(s, special=vow): + return sum(c in special for c in s) + + return count_in(s1) == count_in(s2) + + +def test_alike(): + assert alike("aa", "AA") + assert alike("abcabc", "cbacba") + + +class Solution0: + def halvesAreAlike(self, s: str) -> bool: + return alike(s[:len(s) // 2], s[len(s) // 2:]) + + +def test_sol(): + s = Solution0() + assert s.halvesAreAlike("book") + + +from typing import List +import heapq + + +class Solution1: + def eatenApples(self, apples: List[int], days: List[int]) -> int: + n = len(apples) + ct = 0 + day = 0 + apple_tree = [] + + day_pair = lambda day: [day + days[day] - 1, apples[day]] + add_day_pair = lambda day: heapq.heappush(apple_tree, day_pair(day)) if apples[day] > 0 else None + + add_day_pair(day) + while day < n or apple_tree: + print(day, apple_tree) + if apple_tree: + ct += 1 + if apple_tree[0][1] == 1: + heapq.heappop(apple_tree) + else: + apple_tree[0][1] -= 1 + while apple_tree and apple_tree[0][0] <= day: + heapq.heappop(apple_tree) + print(ct) + day += 1 + if day < n and apples[day] > 0: + add_day_pair(day) + + return ct + + +def test_apples(): + s = Solution1() + assert s.eatenApples([1, 2, 3, 5, 2], [3, 2, 1, 4, 2]) == 7 + assert s.eatenApples([3, 0, 0, 0, 0, 2], [3, 0, 0, 0, 0, 2]) == 5 + assert s.eatenApples([3, 1, 1, 0, 0, 2], [3, 1, 1, 0, 0, 2]) == 5 + assert s.eatenApples( + [0, 19, 19, 19, 11, 14, 33, 0, 28, 7, 0, 28, 7, 0, 21, 16, 0, 22, 0, 13, 8, 0, 19, 0, 0, 2, 26, 2, 22, 0, 8, 0, + 0, 27, 19, 16, 24, 0, 20, 26, 20, 7, 0, 0, 29, 0, 0, 16, 19, 0, 0, 0, 29, 30, 17, 0, 23, 0, 0, 26, 24, 13, 3, + 0, 21, 0, 18, 0], + [0, 5, 1, 16, 7, 10, 54, 0, 40, 2, 0, 23, 4, 0, 20, 18, 0, 40, 0, 22, 8, 0, 35, 0, 0, 3, 24, 1, 8, 0, 10, 0, 0, + 2, 38, 8, 4, 0, 36, 33, 14, 9, 0, 0, 56, 0, 0, 21, 27, 0, 0, 0, 14, 20, 18, 0, 42, 0, 0, 44, 3, 8, 3, 0, 10, 0, + 27, 0]) == 102 + + +class Solution2: + # stuck is determined on the same level hit a one followed by a -1 [1, -1] + # or hit a -1 preceded by a -1 + # or 1 in rightmost + # or -1 in leftmost + def findBall(self, grid: List[List[int]]) -> List[int]: + n, m = len(grid), len(grid[0]) + cur_loc = list(range(m)) + next_loc = [0] * m + + for row_idx in range(n): + print(cur_loc) + row = grid[row_idx] + for bal_idx in range(m): + col_idx = cur_loc[bal_idx] + if (col_idx == -1 or + (col_idx == 0 and row[col_idx] == -1) or + (col_idx == m - 1 and row[col_idx] == 1) or + (col_idx < m - 1 and row[col_idx] == 1 and row[col_idx + 1] == -1) or + (0 < col_idx and row[col_idx] == -1 and row[col_idx - 1] == 1)): + next_loc[bal_idx] = -1 + elif row[col_idx] == 1: + next_loc[bal_idx] = cur_loc[bal_idx] + 1 + else: + next_loc[bal_idx] = cur_loc[bal_idx] - 1 + # setup for next round + cur_loc = next_loc + next_loc = [0] * m + print(cur_loc) + return cur_loc + + +def test_ball(): + s = Solution2() + assert s.findBall( + [[1, 1, 1, -1, -1], [1, 1, 1, -1, -1], [-1, -1, -1, 1, 1], [1, 1, 1, 1, -1], [-1, -1, -1, -1, -1]]) == [1, -1, + -1, -1, + -1] + assert s.findBall([[-1]]) == [-1] + assert s.findBall([[1]]) == [-1] + assert s.findBall( + [[1, 1, 1, 1, 1, 1], [-1, -1, -1, -1, -1, -1], [1, 1, 1, 1, 1, 1], [-1, -1, -1, -1, -1, -1]]) == [0, 1, 2, 3, 4, + -1] + assert s.findBall( + [[1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, + -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1], + [-1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, + -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1], + [1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, + 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1]]) \ + == [-1, -1, 1, -1, -1, -1, -1, 10, 11, -1, -1, 12, 13, -1, -1, -1, -1, -1, 17, -1, -1, 20, -1, -1, -1, -1, + -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] + +from typing import Union + + +class BinTree: + def __init__(self, one=None, zero=None, len=0): + self._one: Union[BinTree, None] = one + self._zero: Union[BinTree, None] = zero + self._len = len + + def is_empty(self) -> bool: + return self._one is None and self._zero is None and self._len == 0 + + def merge(self, other: Union["BinTree", None]) -> "BinTree": + """Merge the two trees together""" + # Note: extending an empty tree adds zero, so check for this special case + if other is None or other.is_empty(): + return self + if self.is_empty(): + return other + merge_len = max(self._len, other._len) + a = self.extend(merge_len) + b = other.extend(merge_len) + return BinTree(one=a._one.merge(b._one) if a._one else b._one, + zero=a._zero.merge(b._zero) if a._zero else b._zero, + len=merge_len) + + @staticmethod + def from_int(n: int) -> "BinTree": + n_str = bin(n)[2:] + n_len = len(n_str) + rv = BinTree() + cur = rv + for idx, digit in enumerate(n_str): + cur._len = n_len - idx + log.debug(cur._len) + if digit == "0": + log.debug("zero") + cur._zero = cur = BinTree() + else: + log.debug("one") + cur._one = cur = BinTree() + return rv + + def add(self, n) -> "BinTree": + return self.merge(BinTree.from_int(n)) + + def extend(self, len: int) -> "BinTree": + """Extend the depth of the tree with leading zeros (if needed).""" + if len <= self._len: + return self + + rv = self + for i in range(1, len - self._len + 1): + new_root = BinTree() + new_root._zero = rv + new_root._len = new_root._zero._len + 1 + if new_root._len != self._len + i: + raise Exception(f"{new_root._len} != {self._len + i} , i={i}") + rv = new_root + return rv + + def __repr__(self): + return f"<{repr(self._zero)}, {repr(self._one)}>" + + +def test_bintree(): + assert repr(BinTree().extend(2)) == "<<, None>, None>" + assert repr(BinTree().from_int(0)) == "<, None>" + assert repr(BinTree().from_int(1)) == ">" + assert repr(BinTree().from_int(3)) == ">>" + assert repr(BinTree().from_int(4)) == ", None>, None>>" + assert repr(BinTree().add(4)) == ", None>, None>>" + assert repr(BinTree().add(0)) == "<, None>" + assert repr(BinTree().add(0).add(1)) == "<, >" + assert repr(BinTree().add(3)) == ">>" + assert repr(BinTree().add(3).add(2)) == ", >>" + + +class Solution: + def maximizeXor(self, nums: List[int], queries: List[List[int]]) -> List[int]: + nums = sorted(set(nums)) + next_num_idx = 0 + queries = sorted(enumerate(queries), key=lambda p: p[1][1]) + rv = [0] * len(queries) + bt = BinTree() + for idx, query in queries: + while next_num_idx < len(nums) and nums[next_num_idx] <= query[1]: + bt = bt.add(nums[next_num_idx]) + next_num_idx += 1 + if bt.is_empty(): + rv[idx] = -1 + else: + q_t = BinTree.from_int(query[0]) + merge_len = max(q_t._len, bt._len) + q_t = q_t.extend(merge_len) + btt = bt.extend(merge_len) + # now are the same length, q_t contains single path, search with btt for max differences and recreate m + m = 0 + while q_t._len != 0: + m *= 2 + if q_t._one and btt._zero: + q_t=q_t._one + btt = btt._zero + elif q_t._zero and btt._one: + m += 1 + q_t = q_t._zero + btt = btt._one + elif q_t._one: + m += 1 + q_t = q_t._one + btt = btt._one + elif q_t._zero: + q_t = q_t._zero + btt = btt._zero + rv[idx] = query[0]^m + return rv + + +def test_maxxor(): + s = Solution() + assert s.maximizeXor(nums = [0,1,2,3,4], queries = [[3,1],[1,3],[5,6]]) == [3, 3, 7] + assert s.maximizeXor(nums = [5,2,4,6,6,3], queries = [[12,4],[8,1],[6,3]]) == [15, -1, 5] + +import time + + +class Timer: + def __init__(self): + self._start = None + self._end = None + + def start(self): + self._start = time.monotonic() + + def stop(self): + self._end = time.monotonic() + + def duration(self): + return self._end - self._start + + def __enter__(self): + self.start() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.stop() + + +import gc + +if __name__ == "__main__": + print("Running some different timings related to 4th problem (b/c too slow and not certain where the time goes)") + # also practicing some matplotlib + xs = range(1, 20_000_000_000, 10_000_000) + N = 10_000 + dat = np.zeros((len(xs), N)) + t = Timer() + gc.set_debug(gc.DEBUG_STATS) + gc.disable() + print(gc.get_count()) + with Timer() as tt: + for x_idx, x in enumerate(xs): + lts = [] + for idx in range(N): + with t: + BinTree.from_int(x) + dat[x_idx, idx] = t.duration() + print(gc.get_count()) + gc.collect() + plt.plot(xs, dat.mean(axis=1)) + plt.plot(xs, np.median(dat, axis=1)) + plt.plot(xs, np.min(dat, axis=1)) + + + diff --git a/leetcode/3sum/3sum.py b/leetcode/3sum/3sum.py new file mode 100644 index 0000000..0d6bbc7 --- /dev/null +++ b/leetcode/3sum/3sum.py @@ -0,0 +1,66 @@ +import bisect +from collections import defaultdict +from typing import List +import time + + +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + ln, numss, sol, d2 = len(nums), nums, set(), defaultdict(list) + self.maked2(d2, numss) + self.findsol(d2, numss, sol) + + return list(sol) + + def findsol(self, d2, numss, sol): + for idx3, k in enumerate(numss): + l = d2[k] + for idx1, idx2 in l: + if idx2 < idx3: + sol.add((numss[idx1], numss[idx2], numss[idx3])) + + def maked2(self, d2, numss): + for idx1, i in enumerate(numss): + for idx2p, j in enumerate(numss[(idx1 + 1):]): + d2[-i - j].append((idx1, idx1 + 1 + idx2p)) + + +import bisect +from collections import defaultdict + + +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + nums.sort() + ln, sols = len(nums), set() + for i in range(ln): + if i + 1 < ln and nums[i] == nums[i + 1]: + continue # only try the highest nums + goal = -nums[i] + j = 0 + k = i - 1 + while j < k: + s2 = nums[j] + nums[k] + if s2 == goal: + sols.add((nums[i], nums[j], nums[k])) + k -= 1 + elif s2 < goal: + j += 1 + else: + k -= 1 + return list(sols) + + +nums = [82597,-9243,62390,83030,-97960,-26521,-61011,83390,-38677,12333,75987,46091,83794,19355,-71037,-6242,-28801,324,1202,-90885,-2989,-95597,-34333,35528,5680,89093,-90606,50360,-29393,-27012,53313,65213,99818,-82405,-41661,-3333,-51952,72135,-1523,26377,74685,96992,92263,15929,5467,-99555,-43348,-41689,-60383,-3990,32165,65265,-72973,-58372,12741,-48568,-46596,72419,-1859,34153,62937,81310,-61823,-96770,-54944,8845,-91184,24208,-29078,31495,65258,14198,85395,70506,-40908,56740,-12228,-40072,32429,93001,68445,-73927,25731,-91859,-24150,10093,-60271,-81683,-18126,51055,48189,-6468,25057,81194,-58628,74042,66158,-14452,-49851,-43667,11092,39189,-17025,-79173,13606,83172,92647,-59741,19343,-26644,-57607,82908,-20655,1637,80060,98994,39331,-31274,-61523,91225,-72953,13211,-75116,-98421,-41571,-69074,99587,39345,42151,-2460,98236,15690,-52507,-95803,-48935,-46492,-45606,-79254,-99851,52533,73486,39948,-7240,71815,-585,-96252,90990,-93815,93340,-71848,58733,-14859,-83082,-75794,-82082,-24871,-15206,91207,-56469,-93618,67131,-8682,75719,87429,-98757,-7535,-24890,-94160,85003,33928,75538,97456,-66424,-60074,-8527,-28697,-22308,2246,-70134,-82319,-10184,87081,-34949,-28645,-47352,-83966,-60418,-15293,-53067,-25921,55172,75064,95859,48049,34311,-86931,-38586,33686,-36714,96922,76713,-22165,-80585,-34503,-44516,39217,-28457,47227,-94036,43457,24626,-87359,26898,-70819,30528,-32397,-69486,84912,-1187,-98986,-32958,4280,-79129,-65604,9344,58964,50584,71128,-55480,24986,15086,-62360,-42977,-49482,-77256,-36895,-74818,20,3063,-49426,28152,-97329,6086,86035,-88743,35241,44249,19927,-10660,89404,24179,-26621,-6511,57745,-28750,96340,-97160,-97822,-49979,52307,79462,94273,-24808,77104,9255,-83057,77655,21361,55956,-9096,48599,-40490,-55107,2689,29608,20497,66834,-34678,23553,-81400,-66630,-96321,-34499,-12957,-20564,25610,-4322,-58462,20801,53700,71527,24669,-54534,57879,-3221,33636,3900,97832,-27688,-98715,5992,24520,-55401,-57613,-69926,57377,-77610,20123,52174,860,60429,-91994,-62403,-6218,-90610,-37263,-15052,62069,-96465,44254,89892,-3406,19121,-41842,-87783,-64125,-56120,73904,-22797,-58118,-4866,5356,75318,46119,21276,-19246,-9241,-97425,57333,-15802,93149,25689,-5532,95716,39209,-87672,-29470,-16324,-15331,27632,-39454,56530,-16000,29853,46475,78242,-46602,83192,-73440,-15816,50964,-36601,89758,38375,-40007,-36675,-94030,67576,46811,-64919,45595,76530,40398,35845,41791,67697,-30439,-82944,63115,33447,-36046,-50122,-34789,43003,-78947,-38763,-89210,32756,-20389,-31358,-90526,-81607,88741,86643,98422,47389,-75189,13091,95993,-15501,94260,-25584,-1483,-67261,-70753,25160,89614,-90620,-48542,83889,-12388,-9642,-37043,-67663,28794,-8801,13621,12241,55379,84290,21692,-95906,-85617,-17341,-63767,80183,-4942,-51478,30997,-13658,8838,17452,-82869,-39897,68449,31964,98158,-49489,62283,-62209,-92792,-59342,55146,-38533,20496,62667,62593,36095,-12470,5453,-50451,74716,-17902,3302,-16760,-71642,-34819,96459,-72860,21638,47342,-69897,-40180,44466,76496,84659,13848,-91600,-90887,-63742,-2156,-84981,-99280,94326,-33854,92029,-50811,98711,-36459,-75555,79110,-88164,-97397,-84217,97457,64387,30513,-53190,-83215,252,2344,-27177,-92945,-89010,82662,-11670,86069,53417,42702,97082,3695,-14530,-46334,17910,77999,28009,-12374,15498,-46941,97088,-35030,95040,92095,-59469,-24761,46491,67357,-66658,37446,-65130,-50416,99197,30925,27308,54122,-44719,12582,-99525,-38446,-69050,-22352,94757,-56062,33684,-40199,-46399,96842,-50881,-22380,-65021,40582,53623,-76034,77018,-97074,-84838,-22953,-74205,79715,-33920,-35794,-91369,73421,-82492,63680,-14915,-33295,37145,76852,-69442,60125,-74166,74308,-1900,-30195,-16267,-60781,-27760,5852,38917,25742,-3765,49097,-63541,98612,-92865,-30248,9612,-8798,53262,95781,-42278,-36529,7252,-27394,-5021,59178,80934,-48480,-75131,-54439,-19145,-48140,98457,-6601,-51616,-89730,78028,32083,-48904,16822,-81153,-8832,48720,-80728,-45133,-86647,-4259,-40453,2590,28613,50523,-4105,-27790,-74579,-17223,63721,33489,-47921,97628,-97691,-14782,-65644,18008,-93651,-71266,80990,-76732,-47104,35368,28632,59818,-86269,-89753,34557,-92230,-5933,-3487,-73557,-13174,-43981,-43630,-55171,30254,-83710,-99583,-13500,71787,5017,-25117,-78586,86941,-3251,-23867,-36315,75973,86272,-45575,77462,-98836,-10859,70168,-32971,-38739,-12761,93410,14014,-30706,-77356,-85965,-62316,63918,-59914,-64088,1591,-10957,38004,15129,-83602,-51791,34381,-89382,-26056,8942,5465,71458,-73805,-87445,-19921,-80784,69150,-34168,28301,-68955,18041,6059,82342,9947,39795,44047,-57313,48569,81936,-2863,-80932,32976,-86454,-84207,33033,32867,9104,-16580,-25727,80157,-70169,53741,86522,84651,68480,84018,61932,7332,-61322,-69663,76370,41206,12326,-34689,17016,82975,-23386,39417,72793,44774,-96259,3213,79952,29265,-61492,-49337,14162,65886,3342,-41622,-62659,-90402,-24751,88511,54739,-21383,-40161,-96610,-24944,-602,-76842,-21856,69964,43994,-15121,-85530,12718,13170,-13547,69222,62417,-75305,-81446,-38786,-52075,-23110,97681,-82800,-53178,11474,35857,94197,-58148,-23689,32506,92154,-64536,-73930,-77138,97446,-83459,70963,22452,68472,-3728,-25059,-49405,95129,-6167,12808,99918,30113,-12641,-26665,86362,-33505,50661,26714,33701,89012,-91540,40517,-12716,-57185,-87230,29914,-59560,13200,-72723,58272,23913,-45586,-96593,-26265,-2141,31087,81399,92511,-34049,20577,2803,26003,8940,42117,40887,-82715,38269,40969,-50022,72088,21291,-67280,-16523,90535,18669,94342,-39568,-88080,-99486,-20716,23108,-28037,63342,36863,-29420,-44016,75135,73415,16059,-4899,86893,43136,-7041,33483,-67612,25327,40830,6184,61805,4247,81119,-22854,-26104,-63466,63093,-63685,60369,51023,51644,-16350,74438,-83514,99083,10079,-58451,-79621,48471,67131,-86940,99093,11855,-22272,-67683,-44371,9541,18123,37766,-70922,80385,-57513,-76021,-47890,36154,72935,84387,-92681,-88303,-7810,59902,-90,-64704,-28396,-66403,8860,13343,33882,85680,7228,28160,-14003,54369,-58893,92606,-63492,-10101,64714,58486,29948,-44679,-22763,10151,-56695,4031,-18242,-36232,86168,-14263,9883,47124,47271,92761,-24958,-73263,-79661,-69147,-18874,29546,-92588,-85771,26451,-86650,-43306,-59094,-47492,-34821,-91763,-47670,33537,22843,67417,-759,92159,63075,94065,-26988,55276,65903,30414,-67129,-99508,-83092,-91493,-50426,14349,-83216,-76090,32742,-5306,-93310,-60750,-60620,-45484,-21108,-58341,-28048,-52803,69735,78906,81649,32565,-86804,-83202,-65688,-1760,89707,93322,-72750,84134,71900,-37720,19450,-78018,22001,-23604,26276,-21498,65892,-72117,-89834,-23867,55817,-77963,42518,93123,-83916,63260,-2243,-97108,85442,-36775,17984,-58810,99664,-19082,93075,-69329,87061,79713,16296,70996,13483,-74582,49900,-27669,-40562,1209,-20572,34660,83193,75579,7344,64925,88361,60969,3114,44611,-27445,53049,-16085,-92851,-53306,13859,-33532,86622,-75666,-18159,-98256,51875,-42251,-27977,-18080,23772,38160,41779,9147,94175,99905,-85755,62535,-88412,-52038,-68171,93255,-44684,-11242,-104,31796,62346,-54931,-55790,-70032,46221,56541,-91947,90592,93503,4071,20646,4856,-63598,15396,-50708,32138,-85164,38528,-89959,53852,57915,-42421,-88916,-75072,67030,-29066,49542,-71591,61708,-53985,-43051,28483,46991,-83216,80991,-46254,-48716,39356,-8270,-47763,-34410,874,-1186,-7049,28846,11276,21960,-13304,-11433,-4913,55754,79616,70423,-27523,64803,49277,14906,-97401,-92390,91075,70736,21971,-3303,55333,-93996,76538,54603,-75899,98801,46887,35041,48302,-52318,55439,24574,14079,-24889,83440,14961,34312,-89260,-22293,-81271,-2586,-71059,-10640,-93095,-5453,-70041,66543,74012,-11662,-52477,-37597,-70919,92971,-17452,-67306,-80418,7225,-89296,24296,86547,37154,-10696,74436,-63959,58860,33590,-88925,-97814,-83664,85484,-8385,-50879,57729,-74728,-87852,-15524,-91120,22062,28134,80917,32026,49707,-54252,-44319,-35139,13777,44660,85274,25043,58781,-89035,-76274,6364,-63625,72855,43242,-35033,12820,-27460,77372,-47578,-61162,-70758,-1343,-4159,64935,56024,-2151,43770,19758,-30186,-86040,24666,-62332,-67542,73180,-25821,-27826,-45504,-36858,-12041,20017,-24066,-56625,-52097,-47239,-90694,8959,7712,-14258,-5860,55349,61808,-4423,-93703,64681,-98641,-25222,46999,-83831,-54714,19997,-68477,66073,51801,-66491,52061,-52866,79907,-39736,-68331,68937,91464,98892,910,93501,31295,-85873,27036,-57340,50412,21,-2445,29471,71317,82093,-94823,-54458,-97410,39560,-7628,66452,39701,54029,37906,46773,58296,60370,-61090,85501,-86874,71443,-72702,-72047,14848,34102,77975,-66294,-36576,31349,52493,-70833,-80287,94435,39745,-98291,84524,-18942,10236,93448,50846,94023,-6939,47999,14740,30165,81048,84935,-19177,-13594,32289,62628,-90612,-542,-66627,64255,71199,-83841,-82943,-73885,8623,-67214,-9474,-35249,62254,-14087,-90969,21515,-83303,94377,-91619,19956,-98810,96727,-91939,29119,-85473,-82153,-69008,44850,74299,-76459,-86464,8315,-49912,-28665,59052,-69708,76024,-92738,50098,18683,-91438,18096,-19335,35659,91826,15779,-73070,67873,-12458,-71440,-46721,54856,97212,-81875,35805,36952,68498,81627,-34231,81712,27100,-9741,-82612,18766,-36392,2759,41728,69743,26825,48355,-17790,17165,56558,3295,-24375,55669,-16109,24079,73414,48990,-11931,-78214,90745,19878,35673,-15317,-89086,94675,-92513,88410,-93248,-19475,-74041,-19165,32329,-26266,-46828,-18747,45328,8990,-78219,-25874,-74801,-44956,-54577,-29756,-99822,-35731,-18348,-68915,-83518,-53451,95471,-2954,-13706,-8763,-21642,-37210,16814,-60070,-42743,27697,-36333,-42362,11576,85742,-82536,68767,-56103,-63012,71396,-78464,-68101,-15917,-11113,-3596,77626,-60191,-30585,-73584,6214,-84303,18403,23618,-15619,-89755,-59515,-59103,-74308,-63725,-29364,-52376,-96130,70894,-12609,50845,-2314,42264,-70825,64481,55752,4460,-68603,-88701,4713,-50441,-51333,-77907,97412,-66616,-49430,60489,-85262,-97621,-18980,44727,-69321,-57730,66287,-92566,-64427,-14270,11515,-92612,-87645,61557,24197,-81923,-39831,-10301,-23640,-76219,-68025,92761,-76493,68554,-77734,-95620,-11753,-51700,98234,-68544,-61838,29467,46603,-18221,-35441,74537,40327,-58293,75755,-57301,-7532,-94163,18179,-14388,-22258,-46417,-48285,18242,-77551,82620,250,-20060,-79568,-77259,82052,-98897,-75464,48773,-79040,-11293,45941,-67876,-69204,-46477,-46107,792,60546,-34573,-12879,-94562,20356,-48004,-62429,96242,40594,2099,99494,25724,-39394,-2388,-18563,-56510,-83570,-29214,3015,74454,74197,76678,-46597,60630,-76093,37578,-82045,-24077,62082,-87787,-74936,58687,12200,-98952,70155,-77370,21710,-84625,-60556,-84128,925,65474,-15741,-94619,88377,89334,44749,22002,-45750,-93081,-14600,-83447,46691,85040,-66447,-80085,56308,44310,24979,-29694,57991,4675,-71273,-44508,13615,-54710,23552,-78253,-34637,50497,68706,81543,-88408,-21405,6001,-33834,-21570,-46692,-25344,20310,71258,-97680,11721,59977,59247,-48949,98955,-50276,-80844,-27935,-76102,55858,-33492,40680,66691,-33188,8284,64893,-7528,6019,-85523,8434,-64366,-56663,26862,30008,-7611,-12179,-70076,21426,-11261,-36864,-61937,-59677,929,-21052,3848,-20888,-16065,98995,-32293,-86121,-54564,77831,68602,74977,31658,40699,29755,98424,80358,-69337,26339,13213,-46016,-18331,64713,-46883,-58451,-70024,-92393,-4088,70628,-51185,71164,-75791,-1636,-29102,-16929,-87650,-84589,-24229,-42137,-15653,94825,13042,88499,-47100,-90358,-7180,29754,-65727,-42659,-85560,-9037,-52459,20997,-47425,17318,21122,20472,-23037,65216,-63625,-7877,-91907,24100,-72516,22903,-85247,-8938,73878,54953,87480,-31466,-99524,35369,-78376,89984,-15982,94045,-7269,23319,-80456,-37653,-76756,2909,81936,54958,-12393,60560,-84664,-82413,66941,-26573,-97532,64460,18593,-85789,-38820,-92575,-43663,-89435,83272,-50585,13616,-71541,-53156,727,-27644,16538,34049,57745,34348,35009,16634,-18791,23271,-63844,95817,21781,16590,59669,15966,-6864,48050,-36143,97427,-59390,96931,78939,-1958,50777,43338,-51149,39235,-27054,-43492,67457,-83616,37179,10390,85818,2391,73635,87579,-49127,-81264,-79023,-81590,53554,-74972,-83940,-13726,-39095,29174,78072,76104,47778,25797,-29515,-6493,-92793,22481,-36197,-65560,42342,15750,97556,99634,-56048,-35688,13501,63969,-74291,50911,39225,93702,-3490,-59461,-30105,-46761,-80113,92906,-68487,50742,36152,-90240,-83631,24597,-50566,-15477,18470,77038,40223,-80364,-98676,70957,-63647,99537,13041,31679,86631,37633,-16866,13686,-71565,21652,-46053,-80578,-61382,68487,-6417,4656,20811,67013,-30868,-11219,46,74944,14627,56965,42275,-52480,52162,-84883,-52579,-90331,92792,42184,-73422,-58440,65308,-25069,5475,-57996,59557,-17561,2826,-56939,14996,-94855,-53707,99159,43645,-67719,-1331,21412,41704,31612,32622,1919,-69333,-69828,22422,-78842,57896,-17363,27979,-76897,35008,46482,-75289,65799,20057,7170,41326,-76069,90840,-81253,-50749,3649,-42315,45238,-33924,62101,96906,58884,-7617,-28689,-66578,62458,50876,-57553,6739,41014,-64040,-34916,37940,13048,-97478,-11318,-89440,-31933,-40357,-59737,-76718,-14104,-31774,28001,4103,41702,-25120,-31654,63085,-3642,84870,-83896,-76422,-61520,12900,88678,85547,33132,-88627,52820,63915,-27472,78867,-51439,33005,-23447,-3271,-39308,39726,-74260,-31874,-36893,93656,910,-98362,60450,-88048,99308,13947,83996,-90415,-35117,70858,-55332,-31721,97528,82982,-86218,6822,25227,36946,97077,-4257,-41526,56795,89870,75860,-70802,21779,14184,-16511,-89156,-31422,71470,69600,-78498,74079,-19410,40311,28501,26397,-67574,-32518,68510,38615,19355,-6088,-97159,-29255,-92523,3023,-42536,-88681,64255,41206,44119,52208,39522,-52108,91276,-70514,83436,63289,-79741,9623,99559,12642,85950,83735,-21156,-67208,98088,-7341,-27763,-30048,-44099,-14866,-45504,-91704,19369,13700,10481,-49344,-85686,33994,19672,36028,60842,66564,-24919,33950,-93616,-47430,-35391,-28279,56806,74690,39284,-96683,-7642,-75232,37657,-14531,-86870,-9274,-26173,98640,88652,64257,46457,37814,-19370,9337,-22556,-41525,39105,-28719,51611,-93252,98044,-90996,21710,-47605,-64259,-32727,53611,-31918,-3555,33316,-66472,21274,-37731,-2919,15016,48779,-88868,1897,41728,46344,-89667,37848,68092,-44011,85354,-43776,38739,-31423,-66330,65167,-22016,59405,34328,-60042,87660,-67698,-59174,-1408,-46809,-43485,-88807,-60489,13974,22319,55836,-62995,-37375,-4185,32687,-36551,-75237,58280,26942,-73756,71756,78775,-40573,14367,-71622,-77338,24112,23414,-7679,-51721,87492,85066,-21612,57045,10673,-96836,52461,-62218,-9310,65862,-22748,89906,-96987,-98698,26956,-43428,46141,47456,28095,55952,67323,-36455,-60202,-43302,-82932,42020,77036,10142,60406,70331,63836,58850,-66752,52109,21395,-10238,-98647,-41962,27778,69060,98535,-28680,-52263,-56679,66103,-42426,27203,80021,10153,58678,36398,63112,34911,20515,62082,-15659,-40785,27054,43767,-20289,65838,-6954,-60228,-72226,52236,-35464,25209,-15462,-79617,-41668,-84083,62404,-69062,18913,46545,20757,13805,24717,-18461,-47009,-25779,68834,64824,34473,39576,31570,14861,-15114,-41233,95509,68232,67846,84902,-83060,17642,-18422,73688,77671,-26930,64484,-99637,73875,6428,21034,-73471,19664,-68031,15922,-27028,48137,54955,-82793,-41144,-10218,-24921,-28299,-2288,68518,-54452,15686,-41814,66165,-72207,-61986,80020,50544,-99500,16244,78998,40989,14525,-56061,-24692,-94790,21111,37296,-90794,72100,70550,-31757,17708,-74290,61910,78039,-78629,-25033,73172,-91953,10052,64502,99585,-1741,90324,-73723,68942,28149,30218,24422,16659,10710,-62594,94249,96588,46192,34251,73500,-65995,-81168,41412,-98724,-63710,-54696,-52407,19746,45869,27821,-94866,-76705,-13417,-61995,-71560,43450,67384,-8838,-80293,-28937,23330,-89694,-40586,46918,80429,-5475,78013,25309,-34162,37236,-77577,86744,26281,-29033,-91813,35347,13033,-13631,-24459,3325,-71078,-75359,81311,19700,47678,-74680,-84113,45192,35502,37675,19553,76522,-51098,-18211,89717,4508,-82946,27749,85995,89912,-53678,-64727,-14778,32075,-63412,-40524,86440,-2707,-36821,63850,-30883,67294,-99468,-23708,34932,34386,98899,29239,-23385,5897,54882,98660,49098,70275,17718,88533,52161,63340,50061,-89457,19491,-99156,24873,-17008,64610,-55543,50495,17056,-10400,-56678,-29073,-42960,-76418,98562,-88104,-96255,10159,-90724,54011,12052,45871,-90933,-69420,67039,37202,78051,-52197,-40278,-58425,65414,-23394,-1415,6912,-53447,7352,17307,-78147,63727,98905,55412,-57658,-32884,-44878,22755,39730,3638,35111,39777,74193,38736,-11829,-61188,-92757,55946,-71232,-63032,-83947,39147,-96684,-99233,25131,-32197,24406,-55428,-61941,25874,-69453,64483,-19644,-68441,12783,87338,-48676,66451,-447,-61590,50932,-11270,29035,65698,-63544,10029,80499,-9461,86368,91365,-81810,-71914,-52056,-13782,44240,-30093,-2437,24007,67581,-17365,-69164,-8420,-69289,-29370,48010,90439,13141,69243,50668,39328,61731,78266,-81313,17921,-38196,55261,9948,-24970,75712,-72106,28696,7461,31621,61047,51476,56512,11839,-96916,-82739,28924,-99927,58449,37280,69357,11219,-32119,-62050,-48745,-83486,-52376,42668,82659,68882,38773,46269,-96005,97630,25009,-2951,-67811,99801,81587,-79793,-18547,-83086,69512,33127,-92145,-88497,47703,59527,1909,88785,-88882,69188,-46131,-5589,-15086,36255,-53238,-33009,82664,53901,35939,-42946,-25571,33298,69291,53199,74746,-40127,-39050,91033,51717,-98048,87240,36172,65453,-94425,-63694,-30027,59004,88660,3649,-20267,-52565,-67321,34037,4320,91515,-56753,60115,27134,68617,-61395,-26503,-98929,-8849,-63318,10709,-16151,61905,-95785,5262,23670,-25277,90206,-19391,45735,37208,-31992,-92450,18516,-90452,-58870,-58602,93383,14333,17994,82411,-54126,-32576,35440,-60526,-78764,-25069,-9022,-394,92186,-38057,55328,-61569,67780,77169,19546,-92664,-94948,44484,-13439,83529,27518,-48333,72998,38342,-90553,-98578,-76906,81515,-16464,78439,92529,35225,-39968,-10130,-7845,-32245,-74955,-74996,67731,-13897,-82493,33407,93619,59560,-24404,-57553,19486,-45341,34098,-24978,-33612,79058,71847,76713,-95422,6421,-96075,-59130,-28976,-16922,-62203,69970,68331,21874,40551,89650,51908,58181,66480,-68177,34323,-3046,-49656,-59758,43564,-10960,-30796,15473,-20216,46085,-85355,41515,-30669,-87498,57711,56067,63199,-83805,62042,91213,-14606,4394,-562,74913,10406,96810,-61595,32564,31640,-9732,42058,98052,-7908,-72330,1558,-80301,34878,32900,3939,-8824,88316,20937,21566,-3218,-66080,-31620,86859,54289,90476,-42889,-15016,-18838,75456,30159,-67101,42328,-92703,85850,-5475,23470,-80806,68206,17764,88235,46421,-41578,74005,-81142,80545,20868,-1560,64017,83784,68863,-97516,-13016,-72223,79630,-55692,82255,88467,28007,-34686,-69049,-41677,88535,-8217,68060,-51280,28971,49088,49235,26905,-81117,-44888,40623,74337,-24662,97476,79542,-72082,-35093,98175,-61761,-68169,59697,-62542,-72965,59883,-64026,-37656,-92392,-12113,-73495,98258,68379,-21545,64607,-70957,-92254,-97460,-63436,-8853,-19357,-51965,-76582,12687,-49712,45413,-60043,33496,31539,-57347,41837,67280,-68813,52088,-13155,-86430,-15239,-45030,96041,18749,-23992,46048,35243,-79450,85425,-58524,88781,-39454,53073,-48864,-82289,39086,82540,-11555,25014,-5431,-39585,-89526,2705,31953,-81611,36985,-56022,68684,-27101,11422,64655,-26965,-63081,-13840,-91003,-78147,-8966,41488,1988,99021,-61575,-47060,65260,-23844,-21781,-91865,-19607,44808,2890,63692,-88663,-58272,15970,-65195,-45416,-48444,-78226,-65332,-24568,42833,-1806,-71595,80002,-52250,30952,48452,-90106,31015,-22073,62339,63318,78391,28699,77900,-4026,-76870,-45943,33665,9174,-84360,-22684,-16832,-67949,-38077,-38987,-32847,51443,-53580,-13505,9344,-92337,26585,70458,-52764,-67471,-68411,-1119,-2072,-93476,67981,40887,-89304,-12235,41488,1454,5355,-34855,-72080,24514,-58305,3340,34331,8731,77451,-64983,-57876,82874,62481,-32754,-39902,22451,-79095,-23904,78409,-7418,77916] + +class Timer: + def __enter__(self): + self.start = time.monotonic() + + def __exit__(self, exc_type, exc_val, exc_tb): + print(exc_type) + print(f"Took {time.monotonic() - self.start}") + +with Timer(): + Solution().threeSum(nums) + diff --git a/leetcode/circperm/circperm.py b/leetcode/circperm/circperm.py new file mode 100644 index 0000000..20cff24 --- /dev/null +++ b/leetcode/circperm/circperm.py @@ -0,0 +1,61 @@ +import time +from typing import List +from itertools import cycle, islice, repeat, chain + + +class Solution: + def row(self, n, i): + seqs = 2**(n - i) + seq_len = 2**i + ls = [[j] * seq_len for j in islice(cycle([1, 0, 0, 1]), seqs)] + return [i for l in ls for i in l] + + def genMatrix(self, n: int) -> List[List[int]]: + return [self.row(n, i) for i in range(n)] + + def c2n(self, c): + b = 1 + r = 0 + for i in range(len(c)): + if c[i] == 1: + r += b + b *= 2 + return r + + def m2n(self, m, n): + r = [] + for i in range(2**n): + c = [m[j][i] for j in range(n)] + r.append(self.c2n(c)) + return r + + def circularPermutation(self, n: int, start: int) -> List[int]: + m = self.genMatrix(n) + p = self.m2n(m, n) + i = p.index(start) + return p[i:] + p[:i] + + +def test1(): + s = Solution() + assert s.row(4, 3) == [1]*8 + [0]*8 + +def test2(): + s = Solution() + assert s.genMatrix(2) == [[1,0,0,1], [1,1,0,0]] + assert s.genMatrix(3) == [[1,0,0,1,1,0,0,1],[1,1,0,0,0,0,1,1],[1,1,1,1,0,0,0,0]] + +def test3(): + s = Solution() + assert s.circularPermutation(2, 3) == [3, 2, 0, 1] + assert s.circularPermutation(3, 7) == [7, 6, 4, 5, 1, 0, 2, 3] + assert s.circularPermutation(3, 5) == [5, 1, 0, 2, 3, 7, 6, 4] + +class Timer: + def __enter__(self): + self.start = time.monotonic() + + def __exit__(self, exc_type, exc_val, exc_tb): + print(exc_type) + print(f"Took {time.monotonic() - self.start}") + diff --git a/leetcode/concatunique/concatunique.py b/leetcode/concatunique/concatunique.py new file mode 100644 index 0000000..d86d2e2 --- /dev/null +++ b/leetcode/concatunique/concatunique.py @@ -0,0 +1,28 @@ +from typing import List, Dict, FrozenSet + + +class Solution: + def maxLength(self, arr: List[str]) -> int: + d = {frozenset(): 0} + for idx in range(len(arr)): + current_letters = set(arr[idx]) + current_len = len(arr[idx]) + if len(current_letters) == current_len: + for sw, l in list(d.items()): + if not current_letters.intersection(sw): + k = frozenset(sw.union(current_letters)) + d[k] = max(l + current_len, d[k]) if k in d else l + current_len + + return max(d.values()) + +def test1(): + arr = ["un","iq","ue"] + assert Solution().maxLength(arr) == 4 + +def test2(): + arr = ["cha","r","act","ers"] + assert Solution().maxLength(arr) == 6 + +def test3(): + arr = ["abcdefghijklmnopqrstuvwxyz"] + assert Solution().maxLength(arr) == 26 diff --git a/leetcode/minbalanced/minbalanced.py b/leetcode/minbalanced/minbalanced.py new file mode 100644 index 0000000..7d1d92c --- /dev/null +++ b/leetcode/minbalanced/minbalanced.py @@ -0,0 +1,55 @@ +from collections import Counter + +class Solution: + def balancedString(self, s: str) -> int: + cts = Counter(s) + cq, cw, ce, cr = cts['Q'], cts['W'], cts['E'], cts['R'] + if cq == cw == ce == cr: + return 0 + best = len(s) + ls = best + scts = {'Q': 0, 'W': 0, 'E': 0, 'R': 0} + goal = ls / 4 # by assumption ls is divisible by 4 + + def possible(scts): + return cq - scts['Q'] <= goal and cw - scts['W'] <= goal and ce - scts['E'] <= goal and cr - scts['R'] <= goal + + def impossible(scts): + return not possible(scts) + + i, j = 0, 0 + while True: + while j < ls and impossible(scts): + scts[s[j]] += 1 + j += 1 + while possible(scts): + scts[s[i]] -= 1 + i += 1 + best = min(best, j - (i - 1)) + if j == ls: + return best + + +def test1(): + s = "QWER" + assert Solution().balancedString(s) == 0 + +def test2(): + s = "QQWE" + assert Solution().balancedString(s) == 1 + +def test3(): + s = "QQQW" + assert Solution().balancedString(s) == 2 + +def test4(): + s = "QQQQ" + assert Solution().balancedString(s) == 3 + +def test5(): + s = "WWQQRRRRQRQQ" + assert Solution().balancedString(s) == 4 + +def test6(): + s = "WQWRQQQW" + assert Solution().balancedString(s) == 3 diff --git a/leetcode/minmoves/minmoves.py b/leetcode/minmoves/minmoves.py index 762517b..d6ddf86 100644 --- a/leetcode/minmoves/minmoves.py +++ b/leetcode/minmoves/minmoves.py @@ -5,8 +5,131 @@ snake = namedtuple("snake", ['tailx', 'taily', 'headx', 'heady']) - class Solution: + def minimumMoves(self, grid: List[List[int]]) -> int: + n = len(grid) # Note: grid is square + s = (0, 0, 1, 0) + start_pos = (0, s) + seen = set(start_pos) + h = deque(maxlen=n * n) + h.append(start_pos) + while h: + steps, (tx, ty, hx, hy) = h.popleft() # pop from beginning (*) + if tx == n - 2 and hy == hx == ty == n - 1: + return steps + + steps += 1 + + def push_new(new_s): + new_item = (steps, new_s) + if not new_s in seen: + h.append(new_item) # add at end (with (*) above ensures that first solution found is shortest) + seen.add(new_s) + + try: + if grid[hy + 1][hx] == grid[ty + 1][tx] == 0: push_new((tx, ty + 1, hx, hy + 1)) + except IndexError: + pass + try: + if grid[hy][hx + 1] == grid[ty][tx + 1] == 0: push_new((tx + 1, ty, hx + 1, hy)) + except IndexError: + pass + try: + if hx > tx and grid[hy + 1][hx] == grid[ty + 1][tx] == 0: push_new((tx, ty, tx, ty + 1)) + except IndexError: + pass + try: + if hy > ty and grid[hy][hx + 1] == grid[ty][tx + 1] == 0: push_new((tx, ty, tx + 1, ty)) + except IndexError: + pass + + return -1 + +class Solution4: + def minimumMoves(self, grid: List[List[int]]) -> int: + cur,cnt, n, seen = [(0,0,0)], 0 , len(grid),set([(0,0,0)]) #(tail_row,tail_col,horizontal_or_verticle) + while cur and (n-1,n-2,0) not in cur: + cnt,tmp = cnt+1, [] + for x,y,dx in cur: + if dx==0: + if y+2 < n and grid[x][y+2] == 0: tmp += [(x,y+1,dx)] + if x+1 < n and (grid[x+1][y] + grid[x+1][y+1]) == 0: tmp += [(x,y,1),(x+1,y,0)] + else: + if x+2 < n and grid[x+2][y] == 0: tmp += [(x+1,y,dx)] + if y+1 < n and (grid[x][y+1] + grid[x+1][y+1]) == 0: tmp += [(x,y,0),(x,y+1,1)] + cur = set(tmp) - seen + seen |= cur + return cnt if cur else -1 + + +class Solution2: + def _moveright(self, s): + return (s[0] + 1, s[1], s[2] + 1, s[3]) + + def _can_right(self, s, grid): + try: + return grid[s[3]][s[2] + 1] == grid[s[1]][s[0] + 1] == 0 + except IndexError: + return False + + def _movedown(self, s): + return (s[0], s[1] + 1, s[2], s[3] + 1) + + def _can_down(self, s, grid): + try: + return grid[s[3] + 1][s[2]] == grid[s[1] + 1][s[0]] == 0 + except IndexError: + return False + + def _rotate(self, s): + return (s[0], s[1], s[0], s[1] + 1) + + def _can_rotate(self, s, grid): + try: + return s[2] > s[0] and grid[s[3] + 1][s[2]] == grid[s[1] + 1][s[0]] == 0 + except IndexError: + return False + + def _rotate_anti(self, s): + return (s[0], s[1], s[0] + 1, s[1]) + + def _can_rotate_anti(self, s, grid): + try: + return s[3] > s[1] and grid[s[3]][s[2] + 1] == grid[s[1]][s[0] + 1] == 0 + except IndexError: + return False + + def _solved(self, s, n): + return s[0] == n - 2 and s[3] == s[2] == s[1] == n - 1 + + def minimumMoves(self, grid: List[List[int]]) -> int: + n = len(grid) # Note: grid is square + s = (0, 0, 1, 0) + start_pos = (0, s) + seen = set(start_pos) + h = deque(maxlen=n*n) + h.append(start_pos) + while h: + steps, s = h.popleft() # pop from beginning (*) + if self._solved(s, n): + return steps + + steps += 1 + + def push_new(new_s): + new_item = (steps, new_s) + if not new_s in seen: + h.append(new_item) # add at end (with (*) above ensures that first solution found is shortest) + seen.add(new_s) + + if self._can_down(s, grid): push_new(self._movedown(s)) + if self._can_right(s, grid): push_new(self._moveright(s)) + if self._can_rotate(s, grid): push_new(self._rotate(s)) + if self._can_rotate_anti(s, grid): push_new(self._rotate_anti(s)) + + return -1 + +class Solution3: def _moveright(self, s): return snake(tailx=s.tailx + 1, taily=s.taily, headx=s.headx + 1, heady=s.heady) @@ -51,6 +174,7 @@ def _solved(self, s, n): return s.tailx == n - 2 and s.heady == s.headx == s.taily == n - 1 def minimumMoves(self, grid: List[List[int]]) -> int: + """deque + namedtumple""" n = len(grid) # Note: grid is square s = snake(tailx=0, taily=0, heady=0, headx=1) start_pos = (0, s) @@ -468,3 +592,6 @@ def test4(): with Timer(): print(Solution().minimumMoves(grid)) + + with Timer(): + print(Solution().minimumMoves(grid)) diff --git a/leetcode/minremoveparens/minremoveparens.py b/leetcode/minremoveparens/minremoveparens.py new file mode 100644 index 0000000..e5e4843 --- /dev/null +++ b/leetcode/minremoveparens/minremoveparens.py @@ -0,0 +1,104 @@ +import random +import time + + +class Solution: + def minRemoveToMakeValid(self, s: str) -> str: + open_idx = [] + remove_idx = [] + ct = 0 + for idx, c in enumerate(s): + if c == "(": + open_idx.append(idx) + ct += 1 + if c == ")": + if ct == 0: + remove_idx.append(idx) + else: + ct -= 1 + + if ct > 0: + remove_idx.extend(open_idx[-ct:]) + + return "".join(c for idx, c in enumerate(s) if not idx in remove_idx) + + def minRemoveToMakeValid_others(self, s: str) -> str: + # NOT MY SOLUTION; copied here to compare timings + # Use a array to save empty + a = list(s) + b = [] + for i, c in enumerate(s): + if c == '(': + b.append(i) + elif c == ')': + if b: + b.pop() + else: + a[i] = '' + + while b: + a[b.pop()] = '' + + return ''.join(a) + +def valid(s): + ct = 0 + for c in s: + if c == "(": + ct += 1 + if c == ")": + if ct == 0: + return False + else: + ct -= 1 + + return ct == 0 + +def test_valid(): + assert valid("") + assert valid("()") + assert valid("asdf(sdsds(dssds(sd)dss(sds)dsds)dsds)dsds") + assert not valid("((") + assert not valid("(()))") + + +def test1(): + s = "lee(t(c)o)de)" + sol = Solution().minRemoveToMakeValid(s) + assert valid(sol) + assert len(sol) == len("lee(t(c)o)de") + +def test2(): + s = "a)b(c)d" + sol = Solution().minRemoveToMakeValid(s) + assert valid(sol) + assert len(sol) == len("ab(c)d") + +def test3(): + s = "))((" + sol = Solution().minRemoveToMakeValid(s) + assert valid(sol) + assert len(sol) == 0 + +def test4(): + s = "(a(b(c)d)" + sol = Solution().minRemoveToMakeValid(s) + assert valid(sol) + assert len(sol) == len("a(b(c)d)") + +class Timer: + def __enter__(self): + self.start = time.monotonic() + + def __exit__(self, exc_type, exc_val, exc_tb): + print(exc_type) + print(f"Took {time.monotonic() - self.start}") + +if __name__ == "__main__": + s = random.choices(["a", "b", "c", "(", ")"], k=10000) + + with Timer(): + Solution().minRemoveToMakeValid(s) + + with Timer(): + Solution().minRemoveToMakeValid_others(s) diff --git a/leetcode/subfolder/subfolder.py b/leetcode/subfolder/subfolder.py new file mode 100644 index 0000000..a07e493 --- /dev/null +++ b/leetcode/subfolder/subfolder.py @@ -0,0 +1,51 @@ +from typing import List +from collections import defaultdict + + +class Solution: + TOK = "666" + + def build(self, folder): + def defd(): + return defaultdict(defd) + + dd = defd() + + for f in folder: + fp = f.split("/")[1:] + d = dd + for k in fp[:-1]: + d = d[k] + if d == self.TOK: + break + else: + d[fp[-1]] = self.TOK + + return dd + + def folders(self, fs, prefix=""): + l = [] + for k in fs.keys(): + if fs[k] == self.TOK: + l.append(prefix + "/" + k) + else: + l.extend(self.folders(fs[k], prefix=prefix+"/"+k)) + return l + + def removeSubfolders(self, folder: List[str]) -> List[str]: + fs = self.build(folder) + print(fs) + return self.folders(fs) + + +def test1(): + folder = ["/a", "/a/b", "/c/d", "/c/d/e", "/c/f"] + assert Solution().removeSubfolders(folder) == ["/a", "/c/d", "/c/f"] + +def test2(): + folder = ["/a", "/a/b/c", "/a/b/d"] + assert Solution().removeSubfolders(folder) == ["/a"] + +def test3(): + folder = ["/a/b/c", "/a/b/ca", "/a/b/d"] + assert Solution().removeSubfolders(folder) == ["/a/b/c", "/a/b/ca", "/a/b/d"] diff --git a/leetcode/treediam/treediam.py b/leetcode/treediam/treediam.py new file mode 100644 index 0000000..15c0e61 --- /dev/null +++ b/leetcode/treediam/treediam.py @@ -0,0 +1,46 @@ +from collections import defaultdict, Counter +from typing import List + + +class Solution: + def furthest(self, d, n): + """Find node furthest from n""" + dists = Counter() + dists[n] = 0 + added = [n] + next_added = [] + while added: + for h in added: + dh = dists[h] + for t in d[h]: + if t not in dists.keys(): + next_added.append(t) + dists[t] = dh + 1 + added = next_added + next_added = [] + print(dists) + return dists.most_common(1)[0] + + def treeDiameter(self, edges: List[List[int]]) -> int: + d = defaultdict(list) + for h, t in edges: + d[h].append(t) + d[t].append(h) + print(d) + # d now is lookup for nbds of node + h, _ = self.furthest(d, edges[0][0]) + print(h) + _, diam = self.furthest(d, h) + return diam + +def test1(): + edges = [[0, 1], [0, 2]] + assert Solution().treeDiameter(edges) == 2 + +def test2(): + edges = [[0, 1], [1, 2], [2, 3], [1, 4], [4, 5]] + assert Solution().treeDiameter(edges) == 4 + +def test3(): + edges = [[0, 1], [0, 2], [1, 3], [0, 4], [1, 5], [2, 6], [1, 7]] + assert Solution().treeDiameter(edges) == 4 diff --git a/mocking/Makefile b/mocking/Makefile new file mode 100644 index 0000000..dbadf24 --- /dev/null +++ b/mocking/Makefile @@ -0,0 +1,5 @@ +VENV=. venv/bin/activate + +venv: + python -m venv venv + ${VENV} ; pip install -r requirements.txt diff --git a/mocking/requirements.txt b/mocking/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/mocking/supermock.py b/mocking/supermock.py new file mode 100644 index 0000000..e78445f --- /dev/null +++ b/mocking/supermock.py @@ -0,0 +1,21 @@ +from undertest import X, B +import unittest.mock as mock +import builtins + + +def test_X(): + x = X() + print(x.f()) + assert x.f() == 10 + + +test_X() + +def test_X_2(): + with mock.patch("builtins.super") as mock_super: + x = X() + mock_super().f = lambda: 3 + print(x.f()) + assert x.f() == 6 + +test_X_2() diff --git a/mocking/undertest.py b/mocking/undertest.py new file mode 100644 index 0000000..34d5549 --- /dev/null +++ b/mocking/undertest.py @@ -0,0 +1,16 @@ +class B: + def f(self): + return 5 + + def h(self): + return 99 + +class X(B): + def f(self): + return super().f() + +x = X() + +def calls(): + x.f() + x.h() diff --git a/supersuper/.gitignore b/supersuper/.gitignore new file mode 100644 index 0000000..eba74f4 --- /dev/null +++ b/supersuper/.gitignore @@ -0,0 +1 @@ +venv/ \ No newline at end of file diff --git a/supersuper/Makefile b/supersuper/Makefile new file mode 100644 index 0000000..4bba94a --- /dev/null +++ b/supersuper/Makefile @@ -0,0 +1,11 @@ +VENV=. venv/bin/activate + +venv: + python -m venv venv + ${VENV} ; pip install -r requirements.txt + +clean: + rm -rf venv + +format: + ${VENV} ; black *.py diff --git a/supersuper/README.md b/supersuper/README.md new file mode 100644 index 0000000..b2ed78f --- /dev/null +++ b/supersuper/README.md @@ -0,0 +1,5 @@ +# super super + +Improving my super understanding. Prepping for some more library design. + +[1] https://rhettinger.wordpress.com/2011/05/26/super-considered-super/ \ No newline at end of file diff --git a/supersuper/ex1.py b/supersuper/ex1.py new file mode 100644 index 0000000..ea99f5a --- /dev/null +++ b/supersuper/ex1.py @@ -0,0 +1,23 @@ +import logging +import sys +import collections + +logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) +log = logging.getLogger("ex1") + + +class LoggingDict(dict): + def __setitem__(self, key, value): + log.info("Setting %r to %r" % (key, value)) + super().__setitem__(key, value) + + +l = LoggingDict() +l[1] = 2 + + +class LoggingOD(LoggingDict, collections.OrderedDict): + pass + + +LoggingOD.mro() diff --git a/supersuper/ex2.py b/supersuper/ex2.py new file mode 100644 index 0000000..7b30cad --- /dev/null +++ b/supersuper/ex2.py @@ -0,0 +1,36 @@ +import logging +import sys +import asyncio +import time + +logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) +log = logging.getLogger("ex2") + + +class LoggingLock(asyncio.Lock): + async def acquire(self): + log.info("Getting lock") + await super().acquire() + log.info("Have lock") + + def release(self): + super().release() + log.info("Released") + + +async def f(lock, label, n=10): + for i in range(n): + async with lock: + log.info(f"{label}({i}):{time.monotonic()}") + await asyncio.sleep(0.5) + + +async def main(): + lock_0 = LoggingLock() + f0 = asyncio.create_task(f(lock_0, "one")) + f1 = asyncio.create_task(f(lock_0, "two")) + + await asyncio.gather(f0, f1) + + +asyncio.run(main()) diff --git a/supersuper/requirements.txt b/supersuper/requirements.txt new file mode 100644 index 0000000..7e66a17 --- /dev/null +++ b/supersuper/requirements.txt @@ -0,0 +1 @@ +black