remove=lambda ಠ‿ಠ:__import__('re').sub(r'[A-Z 0-9]','',ಠ‿ಠ) # I just realized why this is no good :( remove=lambda ಠ‿ಠ:__import__('re').sub(r'[^a-z]','',ಠ‿ಠ) # But this is! x)
1 − remoue=lambda ಠ‿ಠ:__import__('re').sub(r'[A-Z 0-9]','',ಠ‿ಠ) # I just realized why this is no good :(
1 + remove=lambda ಠ‿ಠ:__import__('re').sub(r'[A-Z 0-9]','',ಠ‿ಠ) # I just realized why this is no good :(
2 2 3 − remove=lambda s:''.join(__import__('re').findall(r'[a-z]',s)) # can the regex also do the ''.join() ?
3 + remove=lambda ಠ‿ಠ:__import__('re').sub(r'[^a-z]','',ಠ‿ಠ) # But this is! x)
...?
import unittest TESTS = [((3,4), 7),((1,5), 6),((78,81), 159),((9,21), 30),((5,7), 12),((50, 50), 100),((-50, -250), -20)] # dirty... class MyTest(unittest.TestCase): pass for i,(inp,exp) in enumerate(TESTS): setattr(MyTest, f'test{i}', lambda self,args=inp,x=exp: self.assertEqual(add(*args), x)) TESTS = [((3,4), 7),((1,5), 6),((78,81), 159),((9,21), 30),((5,7), 12),((50, 50), 100),((-50, -250), -1)] # better... but cannot find how to execute them... x) Somebody? class MyTest0(unittest.TestCase): def fixed_tests(self): for i,(inp,exp) in enumerate(TESTS): with self.subTest(i=i): self.assertEqual(add(*inp), exp) if __name__ == '__main__': # doesn't change anything unittest.main()
1 1 import unittest
2 2 3 − class MyTest(unittest.TestCase):
4 − def test0(self):
5 − self.assertEqual(add(3,4), 7)
6 − def test1(self):
7 − self.assertEqual(add(1,5), 6)
8 − def test2(self):
9 − self.assertEqual(add(78,81), 159)
10 − def test3(self):
11 − self.assertEqual(add(9,21), 30)
12 − def test4(self):
13 − self.assertEqual(add(5,7), 12)
14 − def test5(self):
15 − self.assertEqual(add(50, 50), 100)
16 − def test6(self):
17 − self.assertEqual(add(-50, -250), -300)
18 18 19 − if __name__ == '__main__':
4 + TESTS = [((3,4), 7),((1,5), 6),((78,81), 159),((9,21), 30),((5,7), 12),((50, 50), 100),((-50, -250), -20)]
5 + 6 + 7 + # dirty...
8 + class MyTest(unittest.TestCase): pass
9 + 10 + for i,(inp,exp) in enumerate(TESTS):
11 + setattr(MyTest, f'test{i}', lambda self,args=inp,x=exp: self.assertEqual(add(*args), x))
12 + 13 + 14 + 15 + TESTS = [((3,4), 7),((1,5), 6),((78,81), 159),((9,21), 30),((5,7), 12),((50, 50), 100),((-50, -250), -1)]
16 + 17 + 18 + # better... but cannot find how to execute them... x) Somebody?
19 + class MyTest0(unittest.TestCase):
20 + 21 + def fixed_tests(self):
22 + for i,(inp,exp) in enumerate(TESTS):
23 + with self.subTest(i=i):
24 + self.assertEqual(add(*inp), exp)
25 + 26 + 27 + if __name__ == '__main__': # doesn't change anything
20 20 unittest.main()
Performance
divisors=lambda n,r=[]:r.clear()or[d for d in range(1,int(n**.5+1))if n%d<1 and(d-n//d and r.append(n//d)or 1)]+r[::-1]
1 − def divisors(n):
2 − rev=[]
3 − return [d for d,x,r in ((d,*divmod(n,d)) for d in range(1,int(n**.5+1)))
4 − if not r and (d!=x and rev.append(x)or 1)] + rev[::-1]
1 + divisors=lambda n,r=[]:r.clear()or[d for d in range(1,int(n**.5+1))if n%d<1 and(d-n//d and r.append(n//d)or 1)]+r[::-1]
Performance
(just for fun...)
def divisors(n): rev=[] return [d for d,x,r in ((d,*divmod(n,d)) for d in range(1,int(n**.5+1))) if not r and (d!=x and rev.append(x)or 1)] + rev[::-1]
1 1 def divisors(n):
2 − res,rev,h=[],[],int(n**.5)
3 − for d in range(1,h+1):
4 − x,r = divmod(n,d)
5 − if not r:
6 − res.append(d)
7 − if x!=d: rev.append(x)
8 − return res+rev[::-1]
2 + rev=[]
3 + return [d for d,x,r in ((d,*divmod(n,d)) for d in range(1,int(n**.5+1)))
4 + if not r and (d!=x and rev.append(x)or 1)] + rev[::-1]
Performance
def divisors(n): res,rev,h=[],[],int(n**.5) for d in range(1,h+1): x,r = divmod(n,d) if not r: res.append(d) if x!=d: rev.append(x) return res+rev[::-1]
1 1 def divisors(n):
2 2 res,rev,h=[],[],int(n**.5)
3 3 for d in range(1,h+1):
4 − if not n%d:
4 + x,r = divmod(n,d)
5 + if not r:
5 5 res.append(d)
6 − if n//d!=d: rev.append(n//d)
7 + if x!=d: rev.append(x)
7 7 return res+rev[::-1]
Performance
-
i in res
is just... bad. This is O(n) containment check -
int(i/n)
is just... bad too. Use the appropriate operator://
-
sorted(dict.fromkeys(res))
is also... bad:- use a set, not a dict (faster)
- actually, don't use a set or a dict at all: just don't generate duplicates => since you store the divisor and its "complementary" value, you just need to go upto sqrt(n), not n/2
- all numbers are generated in some kind of specific order, so find a way to not sort them => build two lists.
def divisors(n): res,rev,h=[],[],int(n**.5) for d in range(1,h+1): if not n%d: res.append(d) if n//d!=d: rev.append(n//d) return res+rev[::-1]
1 1 def divisors(n):
2 − res=[]
3 − for i in range(1,int(n*0.5)+1):
4 − if i in res: break
5 − if n % i == 0:
6 − res.append(i)
7 − res.append(int(n / i))
8 − 9 − return sorted(dict.fromkeys(res))
2 + res,rev,h=[],[],int(n**.5)
3 + for d in range(1,h+1):
4 + if not n%d:
5 + res.append(d)
6 + if n//d!=d: rev.append(n//d)
7 + return res+rev[::-1]
?
BRAINFUCK VIZUALISER
How to use it:
Debugging commands usable in the BF code:
'?' char in the code to choose the debugging points.
You cnan name the check points with r'\w+' characters after the ?
'!' char to switch on/off the full debugging (print at the execution of each segment)
Other global switches available:
ALL: vizualisation at each step of the code (each segment). Only when you're desperate...
DEACTIVATE: force the deactivation of the vizualisation whatever is found in the code or the other switches are
CHAR_MODE: if True, the tape will display ascii chars instead of numbers (Note: unprintable chars won't show up...)
LIMITER: interrupt the executions after this number of printing. The count is reseted for each test
Here is the kind of output you get, with the code joint (note: I messed up the code of a previously completed kata):
Input: 3
?START
[ 0, 1, 51] tape
[ 0, 0, 1] p
out = ''
?REMOVE_SOME
[ 0, 1, 13, 0] tape
[ 0, 0, 1, 0] p
out = ''
?ISNOTDOT
[ 0, 1, 51, 0, 1] tape
[ 0, 0, 0, 0, 1] p
out = ''
?GET_DECIMAL
[ 0, 1, 51, 0, 0, 0] tape
[ 0, 0, 0, 0, 0, 1] p
out = ''
Input: 3
3 should be 3
SUCCESS
---
Input: 1.5
?START
[ 0, 1, 49] tape
[ 0, 0, 1] p
out = ''
?REMOVE_SOME
[ 0, 1, 11, 0] tape
[ 0, 0, 1, 0] p
out = ''
?ISNOTDOT
[ 0, 1, 49, 0, 1] tape
[ 0, 0, 0, 0, 1] p
out = ''
?START
[ 0, 1, 49, 46, 0] tape
[ 0, 0, 0, 1, 0] p
out = ''
?REMOVE_SOME
[ 0, 1, 49, 8, 0] tape
[ 0, 0, 0, 1, 0] p
out = ''
?ISNOTDOT
[ 0, 1, 49, 46, 0, 1] tape
[ 0, 0, 0, 0, 0, 1] p
out = ''
?START
[ 0, 1, 49, 46, 53, 0] tape
[ 0, 0, 0, 0, 1, 0] p
out = ''
?REMOVE_SOME
[ 0, 1, 49, 46, 15, 0] tape
[ 0, 0, 0, 0, 1, 0] p
out = ''
?ISNOTDOT
[ 0, 1, 49, 46, 53, 0, 1] tape
[ 0, 0, 0, 0, 0, 0, 1] p
out = ''
?GET_DECIMAL
[ 0, 1, 49, 46, 53, 0, 0, 0] tape
[ 0, 0, 0, 0, 0, 0, 0, 1] p
out = ''
Input: 1.5
1.5 should be 2
STDERR:
Traceback:
in <module>
AssertionError
"""
Created on Mon Oct 23 21:59:51 2017
BrainFuck tape, pointer & output vizualizer
@author: Blind4Basics - CodeWars
"""
# -----------------------------------------------------------------
# Debugging commands usable in the BF code:
#
# '?' char in the code to choose the debugging points.
# You cnan name the check points with r'\w+' characters after the ?
# '!' char to switch on/off the full debugging (print at the execution of each segment)
#
#
# Other global switches available:
#
# ALL: vizualisation at each step of the code (each segment). Only when you're desperate...
# DEACTIVATE: force the deactivation of the vizualisation whatever is found in the code or the other switches are
# CHAR_MODE: if True, the tape will display ascii chars instead of numbers (Note: unprintable chars won't show up...)
# LIMITER: interrupt the executions after this number of printing. The count is reseted for each test
#
# -----------------------------------------------------------------
code = """ # not working example
[
tape: _ S digits _ REF DEC S
]
>+
>,
[?START
>++++[<---------->-]<++
?REMOVE_SOME
[
>++++[<++++++++++>-]<--
>>+<
]
<[<]>[>]>
?ISNOTDOT
[-<,>]<
]
>>,
?GET_DECIMAL
[
>++++[<-------->-]
+<<++++
?
[->[->[>]]<<]
?MINUS4
>[[-]<+>]
?LAST
]
<<<[<]>>[.>]
"""
#------------------------------------------------------------
# Test cases:
#
# 'inputs' and corresponding 'expected' values
# EOF char automatically added at the end of each input
#------------------------------------------------------------
inputs = ["3", "1.5", "101", "101.9", "101.2"]
exp = ["3", "2", "101", "102", "101"]
""" GLOBAL SWITCHES """
ALL = False
DEACTIVATE = False
CHAR_MODE = False
LIMITER = 50
import re
def brainFuckInterpreter(code, prog):
def updateVizu(cmdSegment=''):
def formatLst(lst, charMod=False): # Formater: align the cells of the tape and the list for the pointer
formStr = "{: >" + str(max(map(len, map(str, data)), default=1)) + "}"
return "[{}]".format(', '.join(formStr.format(chr(v) if charMod else v) for v in lst))
if DEACTIVATE: return
countDisplay[0] += 1 # Update the number of display already done (cf. LIMITER)
vizu[-1][lastP[0]] = 0 # Erase the previous position of the pointer
vizu[-1][p] = 1 # Place the pointer at the current position
lastP[0] = p # archive the current position of the pointer
vizu[0] = c[0] # archive the current command
out = ''.join(output)
cmd,tape,point = vizu
print( "\n\n{}{} tape\n{} p\nout = '{}'".format(cmdSegment and cmdSegment+"\n",
formatLst(tape, CHAR_MODE),
formatLst(point),
out) )
if LIMITER >= 0 and LIMITER == countDisplay[0]: raise Exception("Too much printing: LIMITER = {}".format(LIMITER))
def tapeLenUpdater(): # Make the tape length consistent with the actual position of the pointer (even if no value yet in the cells)
if p >= len(data):
data.extend( [0] * (p-len(data)+1) )
vizu[-1].extend( [0] * (len(data)-len(vizu[-1])) )
def getNextInput(): # Simulate getting u'0000' when trying to get an input char after their exhaustion
try:
return ord(next(prog))
except StopIteration:
return 0
p, lastP, i = 0, [0], 0 # p = pointer / lastP = previous P position (mutated) / i = segment of code index
data = [0] # Tape initialization
SWITCH, countDisplay = False, [0] # SWITCH: control for the "!" cmd swtich / countDisplay = control for LIMITER (as list to mutate it from a subroutine)
output, vizu = [], ['', data, [0]] # vizu: [cmd, tape, pointer list]
prog = iter(prog)
code = re.findall(r'\++|<+|>+|-+|[,.[\]]|\?\w*|!', code) # Make the executions more compact by using only segments of identical commands (=> '++++', '<<<', '[', '-', ']', check points with identifiers...)
while 0 <= i < len(code):
c = code[i]
if False: print(c, data, p) # activate manually. Only for debugging of the vizualiser itself...
if c[0] == '+': data[p] = (data[p] + len(c)) % 256
elif c[0] == '-': data[p] = (data[p] - len(c)) % 256
elif c[0] == '>': p += len(c) ; tapeLenUpdater()
elif c[0] == '<': p -= len(c) ; tapeLenUpdater()
elif c[0] == '.': output.append(chr(data[p]))
elif c[0] == ',': data[p] = getNextInput()
elif c[0] == '[':
if not data[p]:
depth = 1
while depth > 0:
i += 1
c = code[i]
if c == '[': depth += 1
elif c== ']': depth -= 1
elif c == ']':
if data[p]:
depth = 1
while depth > 0:
i -= 1
c = code[i]
if c == ']': depth += 1
elif c == '[': depth -= 1
# Vizualisation commands/executions
#--------------------
elif c[0] == '?': updateVizu(c) # check point found
if ALL or SWITCH and c[0] != "?": updateVizu(c) # Vizualisation for swithes (avoid double printing for check points)
if c[0] == '!': SWITCH = not SWITCH # Update '!' swtich state
#--------------------
i += 1
return ''.join(output)
#--------------------
# LAUNCH THE TESTS
#--------------------
EOF = chr(0)
for p,e in zip(inputs,exp):
print("Input: ", p)
act = brainFuckInterpreter(code, p+EOF)
print("Input: ", p) # remainder of the input
print(act, " should be ", e) # print actual/expected before assertion
assert act == e
print("SUCCESS\n---\n")