Code
Diff
  • 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 :(
    
    22
    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)
    
Code
Diff
  • remove=lambda s:''.join(filter(str.islower,s))
  • 1
    remove=lambda s:''.join([c for c in s if c.islower()])
    
    1+
    remove=lambda s:''.join(filter(str.islower,s))
    

...?

Code
Diff
  • add=int.__add__
  • 1
    add = lambda x, y : add(x ^ y, (x & y) << 1) if y else x
    
    1+
    add=int.__add__
    
Performance
Code
Diff
  • 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...)

Code
Diff
  • 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]
  • 11
    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
Code
Diff
  • 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]
  • 11
    def divisors(n):
    
    22
        res,rev,h=[],[],int(n**.5)
    
    33
        for d in range(1,h+1):
    
    4
            if not n%d: 
    
    4+
            x,r = divmod(n,d)
    
    5+
            if not r: 
    
    55
                res.append(d)
    
    6
                if n//d!=d: rev.append(n//d)
    
    7+
                if x!=d: rev.append(x)
    
    77
        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.
Code
Diff
  • 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]
  • 11
    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]
    

?

Code
Diff
  • from math import hypot as hypotenuse
        
  • 1
    from math import *
    
    2
    def hypotenuse(a, b): return hypot(a,b)
    
    1+
    from math import hypot as hypotenuse
    
    33
        
    

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")