#esoteric-python

1 messages · Page 67 of 1

rugged sparrow
#

did you figure it out?

#

cause you could always wrap it in a lmabda with a loop

#

im pretty sure

gilded orchid
#

i didn't figure it out but I'll just rearrange my code to fit in a second update

rugged sparrow
#

¯_(ツ)_/¯

#

ok

gilded orchid
#

I just realised I'm still defining variables in my code lmao

#

I have variables from a to j

rugged sparrow
#

haha

rugged sparrow
#

@gilded orchid how the progress coming on the pokemon thing?

#

it seems super cool

gilded orchid
#

almost finished with you attacking, then I just have make the opponent do a random attack and display hp and then I'm done

#

(also I've had to lower my font size 3 times to keep it fully on screen lmao)

rugged sparrow
#

damn thats awesome

gilded orchid
#

Also debugging this thing is an absolute nightmare

    e.update({'g':            d(         (h[2         ],b[3],b[4][(1 if g[3]==0 else                 4)],(2+f[3]),         (1              +         .5           if           h[         1]             in
TypeError: 'int' object is not subscriptable
rugged sparrow
#

i know the feeling

#

i had the same error a ton when i was making minesweeper

gilded orchid
#

I've found 3 bugs here and it still isn't working

#

are you serious

rugged sparrow
#

serious about what? i onelined minesweeper?

gilded orchid
#

no the fact that I've found 3 bugs and it still isn't working

rugged sparrow
#

oh lmao

#

whats the error now?

sick hound
#

it means you're doing py a_tuple // a_list

rugged sparrow
#

prob ```(x[2]//x[3])//50

sick hound
#
>>> () // []
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for //: 'tuple' and 'list'```
#

since 50 isn't a list (hopefully), i'm guessing that x[2] is a tuple and x[3] is a list

#

@gilded orchid

rugged sparrow
#

(hopefully) lmao

sick hound
#

anything can happen

rugged sparrow
#

globals().update('50':[])

sick hound
#

that wouldn't work actually

rugged sparrow
#

jk that doesnt actually let you do 50 == []

sick hound
#

50 is a constant

rugged sparrow
#

yea ik

#

ive tried it before lol

gilded orchid
#

x should just be tuple which just has 5 numbers

#

which means I have to check every time I call that lambda

sick hound
#

try printing x

rugged sparrow
#

can you send lines 12,13,14

sick hound
#
    ((print(x),x[2]//x[3])[1]))```
gilded orchid
#

turns out x is (70, 100, (359, 266, 254, 269, 298), [1], 2, 1.5)

rugged sparrow
#

lmao

#

so how does it get like that?

gilded orchid
#

[(1 if h[3]==0 else 4)] turns out this returns [1]

#

I thought it would just return the number 1

rugged sparrow
#

its inside [] tho, so its a list

sick hound
#
((1 if h[3]==0 else  4))``` will return just `1`
#

but [] makes it a list

gilded orchid
#

Ok, finally got it to cause no errors

#

turns out the tuple was a wrong index

rugged sparrow
#

how?

gilded orchid
#

no clue

#

I tested it when I made it and it worked perfectly

#

but now it's returns 16836 damage

rugged sparrow
#

whats it look like rn?

gilded orchid
#
d=lambda x:(((((((x[1]*2)
//5)+2)*x[0]*
(x[2]//x[3]))             //50)+2)*x[4])
#

Also x is this: (Power, Level, Attack, Defence, STAB)

#

(STAB is a modifier that can either be 1 or 1.5)

rugged sparrow
#

hmm

#
lambda x:((((((2*x[1])//5)+2)*x[0]*(x[2]//x[3]))//50)+2)*x[4]```
#

@gilded orchid ^

#

wait wtf

gilded orchid
#

aren't they the same

rugged sparrow
#

they are

#

but mine worked i think

#

idk why

#

x = [100,2,5,5,1.5]

#

and it returned 9

gilded orchid
#

I have a feeling I've messed up what x is

rugged sparrow
#

print it

gilded orchid
#

my x is (100, 100, 100, 1, 2, 1)

#

I'll work out what it should be, gimme a sec

rugged sparrow
#

thats 6 values

gilded orchid
#

oh wow I'm blind

rugged sparrow
#

lmao

gilded orchid
#

(100, 100, 266, 298, 1) It should be this I think

#

which is why it gave such a high number

#

the defence was set to 1 lmao

rugged sparrow
#

haha

gilded orchid
#
d(         (h[2         ],b[3],b[3],(1 if h[3]==0 else                 4),(2+h[3]),         (1              +         .5           if           h[         1]             in
b[1:3]else 1))

now I have to go back to the code that had 3 errors earlier

rugged sparrow
#

what errors?

gilded orchid
#

*mistakes

#

I had 3 wrong variable names that I'd noticed

rugged sparrow
#

ah

#

nice

gilded orchid
#

(1 if h[3]==0 else 4) I actually have no clue what I was thinking here

#

There isn't any number that needs to be 1 or 4

#

anyway I'm gonna stop spamming this channel now, cya

rugged sparrow
#

maybe it was for spacing?

gilded orchid
#

Turns out I had done two different things for the same index, except I didn't use any square brackets

rugged sparrow
#

whait what?

#

howd you manage that lol

#

also py tryExceptRet = lambda t,args=[],f=lambda e=0:None, e=Exception,r=[],y={}:[ #t is (try lambda), args are passed to t(*args), f is (except lambda),e is Exception or [Exception1,...] y.update({0:type( 'tryExcept',(*(lambda d=[]:[d.append(c) if c.__name__=='ContextDecorator' else None for c in object.__subclasses__()] and d)(),),{ "__init__":lambda self,**kwargs:self.__dict__.update(kwargs), "__enter__":lambda self:None, "__exit__":lambda self, *args:not r.append(self.f(*[args[1]]*self.p)) if any([e in (args[0] or object).__mro__ for e in self.e]) else False } ) }), r.clear(), r.append(y[0](f=f,e=e if isinstance(e,list) else [e],p=f.__code__.co_argcount == 1)(t)(*args)), r[0] ][3] #ret from either block (except block only if try throws Exception) its shorter now

#

oh wait i dont need y anymore

#
tryExceptRet = lambda t,args=[],f=lambda e=0:None, e=Exception,r=[]:[ #t is (try lambda), args are passed to t(*args), f is (except lambda),e is Exception or [Exception1,...]
   r.clear(),
   r.append(
      type(
         'tryExcept',(*(lambda d=[]:[d.append(c) if c.__name__=='ContextDecorator' else None for c in object.__subclasses__()] and d)(),),{
            "__init__":lambda self,**kwargs:self.__dict__.update(kwargs),
            "__enter__":lambda self:None,
            "__exit__":lambda self, *args:not r.append(self.f(*[args[1]]*self.p)) if any([e in (args[0] or object).__mro__ for e in self.e]) else False
         }
      )(f=f,e=e if isinstance(e,list) else [e],p=f.__code__.co_argcount == 1)(t)(*args)),
   r[0]
][2] #ret from either block (except block only if try throws Exception)``` @brisk zenith ive managed to cut alot of length off of it
brisk zenith
#

oh neat!

gilded orchid
#

@brisk zenith what do you think about the idea we said earlier about having a folder on the github for workarounds of lambda restrictions?

brisk zenith
#

on the pydis repo? i'd rather not, because i'd like people to think of ways of doing that themselves. of course, i encourage everyone to take inspiration from other people's submissions by all means. however, having a section of generic esoteric code makes it too easy to copy-paste into your own submissions.

rugged sparrow
#

thats true

rugged sparrow
#
dict(map(lambda x:(x.__name__,x),object.__subclasses__()))['className']``` this is a interesting way of getting any currently initiated class thats in ``object.__subclasses__()`` without having to import it
rugged sparrow
#
{x.__name__:x for x in object.__subclasses__()}['className']```
#

is a more compact way to do it

sick hound
#

@gilded orchid maybe seperatly from pydis we can open an organization for sharing this kind of examples

rugged sparrow
#

@sick hound I can make it

#

what should i call the org?

sick hound
#

i dont know🤔 esoteric-python maybe 😂

#

or onelined-python

rugged sparrow
#

alright lmao

#

tbh making a org is a hassel lol

gilded orchid
#

Couldn't one of us just make a GitHub repo called 'python lambda workarounds'

brisk zenith
#

recipes sounds better

sick hound
#
TryExceptElse = type("TryExceptElse", (__import__("contextlib").ContextDecorator,), {
  "__init__": lambda self, except_ = lambda: None, else_ = lambda: None, exceptions = (Exception,): [setattr(self, name, value) for name, value in locals().items()][0],
  "__enter__": lambda self: None,
  "__exit__": lambda self, exception_type, *_: sum([(True,self.except_())[0] if issubclass(exception_type or type, self.exceptions) else False, (True,self.else_())[0] if exception_type is None else False])
})

# Minified version
TryExceptElse=type("",(__import__("contextlib").ContextDecorator,),{"__init__":lambda self,ex=lambda:None,el=lambda:None,e=(Exception,):[setattr(self,n,v)for n,v in locals().items()][0],"__enter__":lambda x:0,"__exit__":lambda self,e,*_:sum([(1,self.ex())[0]if issubclass(e or type,self.e)else 0,(1,self.el())[0]if e==None else 0])})
#

That's my edited version of the try/except

gilded orchid
#
>>> b = type('test', (), {'__init__':lambda self, a,b:[setattr(self, "a", a),setattr(self, "b", b)]})
         
>>> b(1,2)
         
Traceback (most recent call last):
  File "<pyshell#15>", line 1, in <module>
    b(1,2)
TypeError: __init__() should return None, not 'list'

I'm trying to use the line class thing but I keep on getting this error, how do I fix this?

sick hound
#

you need __init__ to return None

#
[setattr(self, "a", a), setattr(self, "b", b), None][-1]``` try replacing `[setattr(self, "a", a),setattr(self, "b", b)]` with this
gilded orchid
#

oh ok, that makes sense, thanks 😃

sick hound
#

since setattr also returns None you could also use [setattr(self, "a", a), setattr(self, "b", b)][0]

gilded orchid
#

Is there a way to loop through all the arguments the class has and use setattr with them

#

I know you could use map() but can you get a list of all the arguments?

snow beacon
#

.__dir__()

snow beacon
#

Oh, nevermind, that's for attributes.

gilded orchid
#
>>> globals()
Traceback (most recent call last):
  File "<pyshell#27>", line 1, in <module>
    globals()
TypeError: string indices must be integers

I was messing around and somehow got this to happen

#

and this

>>> print('Test')
Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    print('Test')
TypeError: 'int' object is not subscriptable
sick hound
#

what

#

how did you do that

#

@gilded orchid what on earth did you do???

gilded orchid
#

I used globals().update to change builtins to some random number

sick hound
#
>>> print
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not subscriptable```
#

LOL

gilded orchid
#

also changing it to string gives the other error

sick hound
#

yep

gilded orchid
#

I tried to change builtins to a lambda that printed out what got sent to it but it didn't work

sick hound
#

it's subscripting builtins, not calling it

gilded orchid
#

oh right, nvm then lol

sick hound
#
>>> __builtins__=type('',(),{'__getitem__':lambda s,a:(builtins.print(a),builtins.getattr(builtins,a))[1]})()
>>> print
print
<built-in function print>
>>> print('lol')
print
lol```
#

that works though

#
>>> print(int(input()))
print
int
input
42
42```
gilded orchid
#

wow

rugged sparrow
#

@sick hound i made a couple changes to my version of the try/except

#

mine returns the value from either block, also has support for passing the exception to the except block

sick hound
#
>>> import sys
>>> __builtins__ = sys.modules
>>> os
<module 'os' from 'C:\\Users\\Aaay\\AppData\\Local\\Programs\\Python\\Python36\\lib\\os.py'>
>>> sys
<module 'sys' (built-in)>
>>> functools
<module 'functools' from 'C:\\Users\\Aaay\\AppData\\Local\\Programs\\Python\\Python36\\lib\\functools.py'>
>>> importlib
<module 'importlib' from 'C:\\Users\\Aaay\\AppData\\Local\\Programs\\Python\\Python36\\lib\\importlib\\__init__.py'>
>>> sysconfig
<module 'sysconfig' from 'C:\\Users\\Aaay\\AppData\\Local\\Programs\\Python\\Python36\\lib\\sysconfig.py'>
>>> _io
<module 'io' (built-in)>```
rugged sparrow
#
#t is try block (lambda)

#a  is a tuple or list of arguments passed  as t(*a)

#f is except block (lambda) and can have up to 3 arguments; 
#1:Exception Class, 2:Exception Instance, 3:Traceback (*args works)

#e is Exception or [Exception1, Exception2,...]

#return val can be (in order) try() result, except() result, None

tryExceptRet = lambda t,a=(),f=lambda:None, e=Exception,r=[]:[
   r.clear(),
   r.append(type(
      '',
      ({x.__name__:x for x in object.__subclasses__()}['ContextDecorator'],),
      {
         '__enter__':lambda self:setattr(self,'c',f.__code__),
         '__exit__':lambda self,*a:not r.append(
            f(
               *a if self.c.co_flags == 71 else a[0:self.c.co_nlocals]
            )
         ) if any(
            map(
               (a[0] or object).__mro__.count,e if e.__class__ == list else [e]
            )
         ) else False
      }
   )()(t)(*a)),
   r[0],
][2]```
minified
```py
tryExceptRet=lambda t,a=(),f=lambda:None,e=Exception,r=[]:[r.clear(),r.append(type('',({x.__name__:x for x in object.__subclasses__()}['ContextDecorator'],),{'__enter__':lambda self:setattr(self,'c',f.__code__),'__exit__':lambda self,*a:not r.append(f(*a if self.c.co_flags==71else a[0:self.c.co_nlocals]))if any(map((a[0]or object).__mro__.count,e if e.__class__==list else[e]))else False})()(t)(*a)),r[0],][2]
``` @sick hound
sick hound
#

huh

grave rover
#

This seems to be the only issue so far (not including adding all opcodes)

sick hound
#

Generators are function calls

#
>>> dis.dis(c) # (a for b in c)
  1           0 LOAD_CONST               0 (<code object <genexpr> at 0x0000018F0FF27C00, file "", line 1>)
              2 LOAD_CONST               1 ('<genexpr>')
              4 MAKE_FUNCTION            0
              6 LOAD_NAME                0 (c)
              8 GET_ITER
             10 CALL_FUNCTION            1
             12 RETURN_VALUE
>>> dis.dis(c.co_consts[0])
  1           0 LOAD_FAST                0 (.0)
        >>    2 FOR_ITER                10 (to 14)
              4 STORE_FAST               1 (b)
              6 LOAD_GLOBAL              0 (a)
              8 YIELD_VALUE
             10 POP_TOP
             12 JUMP_ABSOLUTE            2
        >>   14 LOAD_CONST               0 (None)
             16 RETURN_VALUE```
#

@grave rover that's not a bug, generators are function calls

grave rover
#

Yeah but I'm not parsing it correctly

#

The order and pops I do aren't done correctly

sick hound
#

...?

#

it looks like you're parsing it fine

#

except for the fact that the names of the functions are missing in MAKE_FUNCTION

#

what's actually the problem?...

#

@grave rover

grave rover
#

found what the bug was

#

now to parse imports...

#
  1           0 LOAD_CONST               0 (0)
              2 LOAD_CONST               1 (('y', 'z'))
              4 IMPORT_NAME              0 (x)
              6 IMPORT_FROM              1 (y)
              8 STORE_NAME               1 (y)
             10 IMPORT_FROM              2 (z)
             12 STORE_NAME               2 (z)
             14 POP_TOP
             16 LOAD_CONST               2 (None)
             18 RETURN_VALUE
```how would I parse this to a tree-view, hmm
calm rampart
#

@grave rover looks like you always get that sequence

#

the 0 is level (number of .'s before imported name), the rest of the module name including package is the import name argument, then sequence of import_from and store, then pop_top

#
>>> dis.dis('from .p.x import y, z as zz')
  1           0 LOAD_CONST               0 (1)
              2 LOAD_CONST               1 (('y', 'z'))
              4 IMPORT_NAME              0 (p.x)
              6 IMPORT_FROM              1 (y)
              8 STORE_NAME               1 (y)
             10 IMPORT_FROM              2 (z)
             12 STORE_NAME               3 (zz)
             14 POP_TOP
             16 LOAD_CONST               2 (None)
             18 RETURN_VALUE```
grave rover
#

I see

#

how would I organize all that properly?

calm rampart
#

i'd probably make either two lists or a list of 2-tuples with the imported names and stored names

#

[and keep in mind the stores can be store_fast if importing inside a function]

#

they can be any kind of store, if the name being imported is defined as global/nonlocal for instance

#

i don't know how you're organizing regular variable stores

#

maybe just define it as a pseudo-function and unpacking assignment, e.g. represent it the exact way you'd represent y, zz = __import__('p.x', ..., ..., ('y', 'z'), 1), except without the name lookup on __import__

#

depends on how abstract you want your syntax tree to get vs the bytecode ops

#

how does AST represent it?

#
>>> ast.dump(ast.parse('from .p.x import y, z as zz'))
"Module(body=[ImportFrom(module='p.x', names=[alias(name='y', asname=None), alias(name='z', asna
me='zz')], level=1)])"```
#

AST distinguishes "y as y" from "y", but bytecode doesn't

grave rover
#

I have it as STORE_NAME(target_var_name, target_token)

#

and I can't peek forwards as to what the next two bytes will be

calm rampart
#

uh?

#

i'm not sure what requires peeking

grave rover
#

well

#

after IMPORT_NAME I cant guarantee if any IMPORT_FROMs are made until I instantiate them

calm rampart
#

i'd consider the entire sequence LOAD_CONST[int] LOAD_CONST[Tuple[str]] IMPORT_NAME (IMPORT_FROM STORE)* POP_TOP as a unit, and generate your tree node based on the contents of that

#

consume the entire bytecode until POP_TOP

grave rover
#

uh

calm rampart
#

if the rest of stuff after IMPORT_NAME doesn't match (IMPORT_FROM STORE)* POP_TOP I'd just consider it unparseable bytecode garbage

grave rover
#

lemme give that to you

calm rampart
#

er it'll be either that or a store for a module import (either non-from or from .)

#

but the second arg (the tuple) would have been None in that case

grave rover
#
  1           0 LOAD_CONST               0 (0)
              2 LOAD_CONST               1 (None)
              4 IMPORT_NAME              0 (sys)
              6 STORE_NAME               0 (sys)
  2           8 LOAD_CONST               0 (0)
             10 LOAD_CONST               1 (None)
             12 IMPORT_NAME              1 (matplotlib.pyplot)
             14 STORE_NAME               2 (matplotlib)
  3          16 LOAD_CONST               0 (0)
             18 LOAD_CONST               2 (('plot', 'legend'))
             20 IMPORT_NAME              1 (matplotlib.pyplot)
             22 IMPORT_FROM              3 (plot)
             24 STORE_NAME               3 (plot)
             26 IMPORT_FROM              4 (legend)
             28 STORE_NAME               4 (legend)
```op after this is POP_TOP
calm rampart
#

like i said, you get either a store right away, or a sequence of import_from/store followed by pop_top

grave rover
#

hm

#

lemme push my latest code to git

calm rampart
#

that's py import sys import matplotlib.pyplot as matplotlib from matplotlib.pyplot import plot, legend

grave rover
calm rampart
#

I guess it's theoretically conceivable in bytecode that it could store both, or have a tuple and only store the module anyway, or do something weirder, but I don't think there's a way to generate that

#
load_const[int] load_const[tuple[str]|None] import_name
    ( (import_from store)+ pop_top
    | store
    | import_star)

or, more precisely based on the value of the tuple argument

load_const[int]
    ( load_const[tuple[str]] import_name (import_from store)+ pop_top
    | load_const[None] import_name store
    | load_const[('*',)] import_name import_star)```
#

(i'm using pseudo regexes to describe my understanding of the grammar of generated bytecode)

#

so after the import_name you'll see either import_from, a store instruction, or import_star

#

like, an excessively literal interpretation of stack-based operands means otherwise you'd do stuff recursively

#

like, the easy way is to say from x import y, z becomes pop_top(import_from(import_from(import_name('x', 0), 'y', 'y'), 'z', 'z')) but that's a difficult tree to work with

#

that'd be more robust to unusual bytecode patterns though i guess

#

since it'd let you import_from from any object rather than just an immediately preceding import_name

#

you'd probably want to at least flatten out sequences of import_from/store

#

so that'd flatten to something import_from(import_name('x', 0, ('y', 'z')), ('y', 'z'), ('y', 'z')) based on a simple rule that if your import_from is followed by another import_from, that gets turned into a list of names and store-destinations instead of just one

#

what do you think @grave rover

grave rover
#

how will I integrate that in my current code tho

calm rampart
#

well

#

i'm not sure where you're building a tree at all in your code

grave rover
#

uh

calm rampart
#

oh nevermind

#

i missed the pops

grave rover
#

the self.pop calls take previous ops and add them to the current token

calm rampart
#

ok

grave rover
#

and self._ops is a list not popped from

calm rampart
#

hmm

#

gah you'd have to mess with all the stores too

grave rover
#

yup

calm rampart
#

ok i'm confused

#

i don't understand how your tree represents opcodes that do not place exactly one value on the stack

grave rover
#

uh

#

wdym

calm rampart
#

how does a store appear in the tree

grave rover
#

sec

calm rampart
#

because fundamentally what's happening with import from is

#

the module is placed on the stack

#

then values are repeatedly retrieved from it with import_from, and they're placed in their destination with store instructions

#

the module stays on the stack while this is happening, it's not placed in a variable

grave rover
calm rampart
#

import_from is basically just like load_attr except it doesn't remove the module from the stack

#

ok i think the whole conceptual problem with your tree structure

#

is that you assume that nothing interacts with operands that it does not pop from the stack

grave rover
#

uh

#

wdym

calm rampart
#

well look at your tree now

grave rover
#

it literally just takes from the function's bytecode

#

and tokenizes it

calm rampart
#
 IMPORT_NAME[1](matplotlib.pyplot, []),
 STORE_NAME[3](plot, IMPORT_FROM[3](plot)),
STORE_NAME[4](legend, IMPORT_FROM[4](legend)),```
the module returned by IMPORT_NAME should, properly, be an argument to both IMPORT_FROM ops
grave rover
#

yeah

#

but idk how to do that in my current code

calm rampart
#

i'm not sure there's an easy way to get from your design to there

#

though

grave rover
#

next(op for op in self._ops[::-1] if op.op_name == "IMPORT_NAME")

calm rampart
#

hmm

#

are there any ops that you're currently handling that return two values?

#

no that won't work either

#

ok uh

#

what if you turned the tree inside out

grave rover
#

Hm

#

Wait

#

What if

calm rampart
#

the tree item for every opcode that returns a value on the stack, contains every operation that occurs while it is still on the stack

grave rover
#

Hm

#

Ideally I'd have the IMPORT_FROM on the IMPORT_NAME since it'd make the other steps easier

#

Like converting bytecode to code

calm rampart
#

so your tree would look like LOAD_CONST(0, [ LOAD_CONST(('plot', 'legend'), [ IMPORT_NAME(matplotlib.pyplot), [ IMPORT_FROM(plot, [STORE_NAME(plot)]), IMPORT_FROM(legend, [STORE_NAME(legend)]), POP_TOP]) ]) ]) ])

grave rover
#

yeah, exactly

#

but I cant access the next op yet

calm rampart
#

no, what i'm saying is

#

don't close the list until the value is popped from the stack

grave rover
#

uh

#

pseudocode?

calm rampart
#

i don't even know how you'd do it in code

#

it'd probably require reworking the whole thing 😦

#

but for example, py [ IMPORT_FROM(plot, [STORE_NAME(plot)]), IMPORT_FROM(legend, [STORE_NAME(legend)]), POP_TOP]) ] is a sequence of operations that works with one value (the module) on the stack, and pops it at the end.

#
    LOAD_CONST(('plot', 'legend'), [
        IMPORT_NAME(matplotlib.pyplot), [...])
    ])``` is a sequence of operations that consumes one excess value from the stack (the LOAD_CONST(0)), since IMPORT_NAME pops two arguments
#

i just don't know how you even can properly represent a mixture of import_from and stores in the current structure

#

eh

#

a weakness in the current tree structure seems to be that it assumes that every operation that doesn't return a value onto the stack (e.g. stores) happens at the top level, not inside the "arguments" to another operation

#

and I don't know how to fix that

grave rover
#

wdym?

#

you don't do x = some_func(ASSIGNMENT)

calm rampart
#

sure

#

in python code

#

but in bytecode, you're absolutely storing plot while the module operand that will be used for import_from(legend) is still on the stack

#

it's not even some_func(ASSIGNMENT), not really

#

the assignment isn't being passed to some_func, it's just happening while the argument list for some_func is being set up

grave rover
#

hmm...

#

I mean you can use self.last for last op without popping

calm rampart
#

so it's like if you had some_func(ASSIGNMENT, 1) and some_func only actually sees 1 as the argument

grave rover
#

I need to see code to understand what you mean tbh

calm rampart
#

ok wait what

#

so how does that show up in the tree representation? the same operation shows up multiple places?

#

i didn't know that was an option - it shouldn't be, you could very easily make trees that can't be represented in bytecode that way

#

ok i am not talking about your code - i am talking about how the bytecode itself works

#

like

#

if you use self.last for IMPORT_FROM, what does that make your tree look like?

#

this? py STORE_NAME[3](plot, IMPORT_FROM[3](plot, IMPORT_NAME[1](matplotlib.pyplot, []))), STORE_NAME[4](legend, IMPORT_FROM[4](legend, IMPORT_NAME[1](matplotlib.pyplot, []))), POP_TOP[0](IMPORT_NAME[1](matplotlib.pyplot, [])),

grave rover
#

uhh

#

it would work for the first IMPORT_FROM

#

not for the second since for the second one self.last becomes a STORE_NAME

calm rampart
#

ok that's another problem then

#

STORE_NAME doesn't put anything on the stack

#

there needs to be a way to reference the expression generating the top (and second, etc) item on the stack for any of this to work at all

#

not just "the last operation executed regardless of if it put anything on the stack or not"

#

i really do think your code needs to be able to recognize patterns rather than simply going one instruction at a time

#

i haven't looked at it enough to know how you're going to deal with conditionals, loops, etc, but any approach needs to be able to handle embedded conditionals inside expressions, not just a top-level "basic block" pass

grave rover
#

I'm not exactly emulating the stack

#

I'm just adding ops to a list

#

I leave running the code to the end user

calm rampart
#

ok

#

but if you're trying to turn it into a tree, you need the stack to know what operations feed their results into what other operations

#

a list doesn't have that issue, but i thought you were trying to make a tree

grave rover
#

Yeah but like, I have a list and tree and both are added to at the same time, the tree just gets popped from for building the tree

rugged sparrow
#

@sick hound in case you care, i made with:

#
#w is the function to do work with, orig syntax is (with w():)

#f is executed in the context of w.
#If s is set to a string, and that string is the name of the first var in f, w will be passed through it

#a is the args passed to f, after the first var if s is set

#will return the return val of f

withFunc = lambda w,f,s='',a=[]:type(
   '',
   ({x.__name__:x for x in object.__subclasses__()}['ContextDecorator'],),
   {
      '__init__':lambda self,c:setattr(self,'c',c),
      '__enter__':lambda self:self.c.__enter__(),
      '__exit__':lambda self,*args,**kwds:self.c.__exit__(*args,**kwds)
   }
)(w)(f)(*([w] if (lambda c=f.__code__.co_varnames:c and s==c[0])() else [])+a)```
arctic bridge
#

Beautiful

rugged sparrow
#

did you see my tryExcept from earlier @arctic bridge ?

#
#t is try block (lambda)

#a  is a tuple or list of arguments passed  as t(*a)

#f is except block (lambda) and can have up to 3 arguments; 
#1:Exception Class, 2:Exception Instance, 3:Traceback (*args works)

#e is Exception or [Exception1, Exception2,...]

#return val can be (in order) try() result, except() result, None

tryExceptRet = lambda t,a=[],f=lambda:None, e=Exception,r=[]:[
   r.clear(),
   r.append(type(
      '',
      ({x.__name__:x for x in object.__subclasses__()}['ContextDecorator'],),
      {
         '__enter__':lambda self:setattr(self,'c',f.__code__),
         '__exit__':lambda self,*a:not r.append(
            f(
               *a if self.c.co_flags == 71 else a[0:self.c.co_nlocals]
            )
         ) if any(
            map(
               (a[0] or object).__mro__.count,e if e.__class__ == list else [e]
            )
         ) else 0
      }
   )()(t)(*a)),
   r[0],
][2]
#

it can all be onelined, because why not

arctic bridge
#

Nice

rugged sparrow
#

i might try to make a oneline code generator this summer

grave rover
#

neat

grave rover
#

9<<(7<<60) largest possible number in Python using only 10 bytes of code

marsh void
#

hmm interestin'

grave rover
#

More than 10^242944768872896860

marsh void
#

Yeah, throws MemoryError, but what’s the point of it anyway? DraggoShrug

grave rover
#

This number is so big that it requires almost 1 EiB of memory to hold it, which is a little bit more than I have on my computer. Luckily, you only need to use around 0.2% of the world's storage space as swap to hold it. The value in binary is 1001 followed by 8070450532247928832 zeros.

marsh void
#

Huh, not bad 🤔

#

Well, cool interesting thing to know about

brazen geyser
#
STORE_DEREF(i)¶
Stores TOS into the cell contained in slot i of the cell and free variable storage.

So is this 'cell and free variable storage' essentially a list?

#

what is a 'cell' in this context?

rugged sparrow
#

@brazen geyser what?

brazen geyser
#

There are a number of places where things are stored in/loaded from the 'cell and free variable storage'

#

I've been able to glean what free variables are, but what are cells?

#

and what/where are they stored in?

#

is it basically just a list?

rugged sparrow
#

So afaik, python has a set of "free" variables

#

Like there is a technical maximum per script

#

And there is extended variables too

#

@sick hound might know

brazen geyser
#

ok so this is the C code

        case TARGET(STORE_DEREF): {
            PyObject *v = POP();
            PyObject *cell = freevars[oparg];
            PyObject *oldobj = PyCell_GET(cell);
            PyCell_SET(cell, v);
            Py_XDECREF(oldobj);
            DISPATCH();
        }
#

now to track down PyCell_SET

#

and GET

#
#define PyCell_GET(op) (((PyCellObject *)(op))->ob_ref)
#define PyCell_SET(op, v) (((PyCellObject *)(op))->ob_ref = v)
#
LIST_APPEND(i)¶
Calls list.append(TOS[-i], TOS). Used to implement list comprehensions.
#

what does this even mean? append only takes one argument

rugged sparrow
#

@brazen geyser could be pseudo code for the C implementation. Which would prob be given a pointer to the first item of the list and the item to append

brazen geyser
#

@rugged sparrow thinking about it again, i reckon TOS[-i] is meant to be self and it's literally list.append as in the unbound method

rugged sparrow
#

oh that makes sense

grave rover
#

can you show any disassemblies that have STORE_DEREF?

marsh void
grave rover
#

Oof

marsh void
#

And huh, sorry if it is considered as a meme

calm rampart
#

@grave rover STORE_DEREF is associated with nonlocal

#
>>> def f():
...  x = None
...  def g():
...   nonlocal x
...   x = 1
...``` ```py
Disassembly of <code object g at 0x0000000002AF2DB0, file "<stdin>", line 3>:
  5           0 LOAD_CONST               1 (1)
              2 STORE_DEREF              0 (x)
              4 LOAD_CONST               0 (None)
              6 RETURN_VALUE```
#

[and just like the other stores, you can get it from any that assigns a name, e.g. def/class/import]

grave rover
#

I see

#

So freevars are the vars that'll be set to outside to the func

sick hound
#
>>> from ctypes import*;1/(cast(pointer(c_int(0x5F37642F-(cast(pointer(c_float(42)),POINTER(c_int))[0]>>1))),POINTER(c_float))[0])**2
39.27731871084027```
desert garden
#

Does anyone have a snippet to map dict.__getattr__ to use dict.__getitem__ so you can use JS-style dict lookups?

rugged sparrow
#

@desert garden you can always make an inherited class. but i assume you want to make normal dicts behave that way?

desert garden
#

Yeah

rugged sparrow
#

hmm

#
class dictJS(dict):
     def __getattr__(self,item):
             return self.__getitem__(item)``` cause thats all the new class needs
desert garden
#

I'm on mobile right now but in the past I've tried ctypes'ing it in and it didn't work

#

I want native {}s to use it

rugged sparrow
#

maybe could replace builtins dict

#

one sec

#

nope :/

#

ill do some research tho

tepid glacier
#

can forbiddenfruit overload dunders now?

rugged sparrow
#

i think?

#

im about to test it

tepid glacier
#
Traceback (most recent call last):
  File "test.py", line 8, in <module>
    curse(dict, '__getattr__', get_item)
  File "/home/jeremiah/.pyenv/versions/3.7.2/lib/python3.7/site-packages/forbiddenfruit/__init__.py", line 412, in curse
    _curse_special(klass, attr, value)
  File "/home/jeremiah/.pyenv/versions/3.7.2/lib/python3.7/site-packages/forbiddenfruit/__init__.py", line 329, in _curse_special
    tp_as_name, impl_method = override_dict[attr]
KeyError: '__getattr__'
#

rip

rugged sparrow
#

yea

#

:/

tepid glacier
#

yeah I guess someone'll come up with some ctypes voodoo

rugged sparrow
#

probably

desert garden
#

My usually ctypes voodoo didn't work on it when I tried, oddly

#

It can patch in things like str.spongebob(), but I think there's something special about dict.__getattr__

rugged sparrow
#

@desert garden dict.__getattr__ is actually dict.__getattribute__ first of all

desert garden
#

I'm on mobile :). Don't wanna type that out lol

rugged sparrow
#
>>> x.__getattribute__
Segmentation fault (core dumped)
chronos@localhost ~ $ ``` how to know youre getting somewhere lmao
desert garden
#

Lmao

rugged sparrow
#
>>> proxy_builtin(dict)['__getattribute__'] = lambda self,item:self.__getitem__(item)
>>> x= {'x':1}
>>> x
{'x': 1}
>>> x.x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'x'
>>> x.__getattribute__
<bound method <lambda> of {'x': 1}>
>>> x.__getattribute__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: <lambda>() missing 1 required positional argument: 'item'
>>> x.__getattribute__(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
KeyError: 1
>>> x.__getattribute__('x')
1
>>> ``` @desert garden
#

i dont think that dict actually uses __getattribute__ to get attributes

#

its just for subclasses

desert garden
#

There should be some way to force it to though

rugged sparrow
#

true

#
import ctypes

class PyObject(ctypes.Structure):
   pass

Py_ssize_t = hasattr(ctypes.pythonapi, 'Py_InitModule4_64') and ctypes.c_int64 or ctypes.c_int

PyObject._fields_ = [('ob_refcnt', Py_ssize_t),('ob_type', ctypes.POINTER(PyObject)),]

class SlotsPointer(PyObject):
   _fields_ = [('dict', ctypes.POINTER(PyObject))]

def proxy_builtin(_class):
   name = _class.__name__
   slots = getattr(_class, '__dict__', name)
   pointer = SlotsPointer.from_address(id(slots))
   namespace = {}
   ctypes.pythonapi.PyDict_SetItem(ctypes.py_object(namespace),ctypes.py_object(name),pointer.dict)
   return namespace[name]

``` @desert garden this is what im trying rn
#
>>> proxy_builtin(list)['index'] = lambda *args:print('test')
>>> [1].index()
test``` btw this works. so i think that overriding any of the "magic" methods is difficult
#

ctypes.memmove didnt work

rugged sparrow
#

honestly @brisk zenith probably would know more towards getting that to work

brisk zenith
#

@rugged sparrow builtin methods are written in C, you cannot simply overwrite them with python functions. instead, you should use the ctypes.CFUNCTYPE decorator/function to convert it to a C function pointer

rugged sparrow
#

how would i then apply it?

brisk zenith
#

well, builtin methods are just pointers to C functions, so you just overwrite the pointer in memory

rugged sparrow
#

And I can get the current location using ctypes I assume?

#

@brisk zenith how can i get the original functions pointer?

brisk zenith
#

uhh.. depends on its location within the PyTypeObject C struct

#

it's kinda really tricky to do

rugged sparrow
#

ah

brisk zenith
#

without spaghetti code, that is

#

my cpystructs code would help with it somewhat though

rugged sparrow
#

did you ever post that?

brisk zenith
#

yeah, but i haven't had the time to bring out any updates for it and it's still very WIP

rugged sparrow
#

ah so it might not work for this?

brisk zenith
#

it would certainly help but i recommend you use it as a reference until i get time to work on it properly and make it fully functional and whatnot.

rugged sparrow
#

aight

#

thanks

sick hound
#

I was using the snippet @rugged sparrow shared, (i actually took it from stackoverflow)

#

it sometimes gives segfault, sometimes runs as expected

rugged sparrow
#

Yeah that's where I got it

sick hound
#
FORBID_BY_TYPE_ACCESS = {
    'FunctionType': [
        "__globals__",
    ]
}
...
            for typ, forbids in FORBID_BY_TYPE_ACCESS.items():
                members = get_members(getattr(types, typ))
                for forbidden in forbids:
                    del members[forbidden]
#

this is the code

rugged sparrow
#

@gilded orchid how's the Pokemon thing going?

brisk zenith
#

i am curious about this too

gilded orchid
#

I kind of stopped doing it as I couldn't really finish it due to really poor planning on my part, I might restart it sometime though

gilded orchid
#

The main mistakes I made were not doing the damage formula correctly (I missed of out two of the modifiers, critical hits and the random 85% to 100% modifier) and using way to many variables

rugged sparrow
#

@gilded orchid I might give it a shot if you don't mind

gilded orchid
#

Yeah I don't mind, you'll probably do it 10x better then I ever could lmao

rugged sparrow
#

Lmao aight

rugged sparrow
#

@gilded orchid @brisk zenith https://repl.it/@chilaxan/Pokemon-One-Liner in case you want to see what i have so far

gilded orchid
#

Are you doing it for the code art challenge, or just as a one-liner?

rugged sparrow
#

im one-lining it first

#

then im gonna format it into the Pokemon word and maybe a pokeball

gilded orchid
#

oh ok

#

Also just skimming through your code, wouldn't it be shorter to do map(lambda a:setattr(self,a,locals()[a]),['name','type','stats','moves']) instead of

        setattr(self,'name',name),
        setattr(self,'type',pType),
        setattr(self,'stats',stats),
        setattr(self,'moves',moves),

in the pokemon class?

rugged sparrow
#

yea

#

when i first code it, i do it the long way as its easier to debug

gilded orchid
#

oh ok, makes sense

rugged sparrow
#

yea 😃

#

what did you think of my type based attack strength?

#

with my hugeass dictionary lmao

gilded orchid
#

i guess it works lmao

rugged sparrow
#

its definitely shorten-able

#

but ill do that after it all works

gilded orchid
#

I tried storing the type weaknessess with the actual pokemon itself

#

But it kind of looked like a mess

rugged sparrow
#

this is kinda a mess lol

gilded orchid
#
    'getCurrentStat':lambda self,user,stat:__import__('math').floor(((self.__dict__[stat] + __import__('random').choice(range(5,15)))*2*user.level)//100)+((user.level+10) if stat=='hp' else 5)

What does this do?

rugged sparrow
gilded orchid
#

oh right

#

where do you keep IVs and EVs?

rugged sparrow
#

im not doing them lmao

#

i couldnt figure out a good way to implement

#

and they dont have that much of an effect in a single battle

gilded orchid
#

You could just make the IVs always 31

rugged sparrow
#

IVs in gen 1 were only in the range 5-15

#

i think

gilded orchid
#

oh yeah, weren't they called DVs in gen 1

rugged sparrow
#

yea

#

so i just choose a random number on creation of the move

gilded orchid
#

I guess that works

rugged sparrow
#

yea

#

¯_(ツ)_/¯

gilded orchid
#

Is there a way to make a lambda (as an argument of a lambda) that changes the locals() in a lambda and makes them actually update

#

wow I worded that badly

rugged sparrow
#

i dont think you can change the locals() in a lambda at all

gilded orchid
#

I guess abusing globals() works just as well

rugged sparrow
#

true

#

if its a small value, then ill just have mutable list in the defaults of the lambda and add the value to it with append

gilded orchid
#

Is there a way to have arguments in a lambda without using any spaces?

rugged sparrow
#

like lambda x,y,z:(x,y,z)?

gilded orchid
#

There's a space between lambda and x (i'm was trying to do a oneliner with 0 spaces)

rugged sparrow
#

Ah

#

umm

#

one sec

#

you can do lambda\ x:x

#

@gilded orchid but that has an extra newline

sick hound
#

that's not one line anymore though

rugged sparrow
#

yea ik

#

tabs are ignored if you want to use a tab

gilded orchid
#

nvm

snow beacon
#

Does lambda*x: work?

#

Yes it does. @rugged sparrow

rugged sparrow
#

Ah sweet

#

Makes sense

stray needleBOT
brisk zenith
#

challenge 08 is here: python REPL!

this time we're looking for novel solutions to executing python code, all wrapped up in a nice interactive shell (much like the regular python REPL). you can make the code as weird, short, or even as beautiful as you want, but the way it works internally should be the most interesting and unique part of it. you can find more information about the task and restrictions on the repo: https://github.com/python-discord/esoteric-python-challenges/tree/master/challenges/08-python-repl

for those of you who are still working on previous challenges, don't worry. you can still make submissions for any challenge at any point, so just keep working on it as normal :D
i'd also like to thank the other event handlers for planning out this challenge, as i've been too busy to do it myself recently. of course, if you have any ideas that you think would be good for the next challenge, just let me know!

#

oh, and i know that there are a few more PRs that i should merge. i'll do that tomorrow, i don't have any time now. :)

rugged sparrow
#

oooo that looks like a tricky challenge

sick hound
#

wait
is this basically you have to write your own python code parser/

gilded orchid
#

in python

#

that sounds like a nightmare

tropic night
#

without eval exec and compile. that is just code masochism @brisk zenith 😄

sick hound
#

Is it allowed to use AST?

dense spire
#

yes.

#

that's the kind of thing we're hoping you'll use.

sick hound
#

I think i need to add a few more bytecodes and a repl then its done

rugged sparrow
#

@gilded orchid were you planning on doing ascii art for the pokemon?

fluid dove
#

for the challenge, perhaps have code that sinputted written to a py file as a method thats imported on startup, and reload the module and run the method u just wrote to it

gilded orchid
#

@rugged sparrow nope I wasn't planning to do that

#

weird question, is there a way to print something without using any brackets?

rugged sparrow
#

like no ()? @gilded orchid

gilded orchid
#

Yeah

rugged sparrow
#

i dont think so

#

@gilded orchid progress btw https://repl.it/@chilaxan/Pokemon-One-Liner

gilded orchid
#

oh wow

#

I close are you to finishing it?

rugged sparrow
#

so i need to do the actual game loop

#

and then format it to the Pokemon logo

rugged sparrow
sick hound
#

@rugged sparrow so how u learned coding?

rugged sparrow
#

i found it interesting

#

so i taught myself

#

trial and error + stackoverflow

sick hound
#

oo

rugged sparrow
#

yea

#

and i learned python this year

gilded orchid
#

Onix's Earthquake Missed!
doesn't earthquake have 100% accuracy

#

wait did you implement the 1/255 bug?

#

@rugged sparrow

rugged sparrow
#

yea @gilded orchid

#

cause i wanted to replicate gen1

gilded orchid
#

(this was the start of the battle)

rugged sparrow
#

haha

#

unlucky

#

wait actually

#

one sec

marsh void
#

it's getting miss a lot though

rugged sparrow
#

yah i just realized i forgot to make it 100% accurate

#

one sec

gilded orchid
#

yeah I just missed 4/7

rugged sparrow
#

note that i dont have PP yet

#

so you can just spam powerful moves

gilded orchid
#

also does it always do move one if you type something that isn't 1-4?

rugged sparrow
#

yea

#

i could have implemented my oneline input loop but i wanted to get a first version done

gilded orchid
#

could you use the PokeAPI to let the user choose their pokemon?

rugged sparrow
#

nah cause i had to implement the moves

gilded orchid
#

PokeAPI also has moves though

rugged sparrow
#

not written in python

#

and not with the special effects of the move

grave rover
#

how to make a python REPL
-> add an input field
-> add an output field
-> run os.system("python -c '<code with proper quotes>'")
-> done

brisk zenith
#

yes but we're looking for novel solutions. if you're not going to think of weird and interesting ways to solve the challenge, then don't. :D

rugged sparrow
#

@grave rover i dont think that would solve the challenge. doesnt preserve variables

brisk zenith
#

that too.

grave rover
#

I know, just memeing

#

I might actually go for a fancy REPL

#

sucks not having exec tho

rugged sparrow
#

oh yea @brisk zenith if i want to have files like .pngs in my submission, should i do a folder?

#

thinking about using fabulous and some 8 bit images to add something to the pokemon thing when i reformat it

brisk zenith
#

yeah for sure. if your submission is more than one file, use a folder to avoid cluttering everything else. seems like you're putting a lot of effort into this, very looking forward to it :D

grave rover
#

I might try some fancy stuff with prompt_toolkit

rugged sparrow
#

Sounds good

#

It may be a bit till it's well and truly done tho. There isn't any time limit on submitting right? @brisk zenith

grave rover
#

dont think so

brisk zenith
#

not at all, please don't feel rushed or anything. you could even make submissions for the first challenges if you find yourself bored at any point, i don't mind.

rugged sparrow
#

Sweet

grave rover
#

for now imma finish my Python to C++ code conversion tho

#

writing C++ is hard :(

trim linden
#

i just found out about this

#

JSFuck is an esoteric subset of JavaScript, where code is written using only six characters: [, ], (, ), !, and +. The name is derived from Brainfuck, an esoteric programming language that also uses a minimalistic alphabet of only punctuation. Unlike Brainfuck, which require...

#

owo

#

its scary

rugged sparrow
#

I wonder if you can do something like that with python

stone apex
#

Don't spam attachments so fast

#

The bot nuked you

#

!unmute @rugged sparrow

night quarryBOT
#

:incoming_envelope: :ok_hand: Un-muted @rugged sparrow.

rugged sparrow
#

yah my bad

gilded orchid
#

With colour?

sick hound
#

I'm looking forward to trying out making a REPL
Unfortunately I have exams so I must wait :(

rugged sparrow
#

@gilded orchid with ANSI escape codes

rugged sparrow
#

gotta love on the spot patching of imported modules ```py
setattr(f,'init',(lambda self,image:[setattr(self,'img',image.convert('RGBA')),self.resize(None)][0])),

#

*this was to allow passing a PIL Image instance instead of a file path

brisk zenith
#

@sick hound that's fine, just focus on your exams and work on it when you've got time :D

#

i'll be making my own solutions to the challenges when i have time

fast torrent
#

Juan having "time"

brisk zenith
#

fuck off you dosy bellend <3

fast torrent
#

Haha

desert garden
#

No using eval? Sounds like a chance for globals()['e' + 'v' + 'a' + 'l'](input())

rugged sparrow
#

globals()['__builtins__'].__dict__['e'+'v'+'a'+'l'] @desert garden

desert garden
#

Oh right yeah

#

Forgot builtins aren't applied directly to global scope

brisk zenith
#

(that still counts as eval and is therefore an uninteresting solution ;D)

rugged sparrow
#

@brisk zenith would getting eval through a really weird way be good? Like using ctypes and grabbing the memory address?

#

It's still eval but its weird eval

sick hound
#

lol

#

weird eval

brisk zenith
#

i'd be impressed if you can somehow call the default eval C function of the main interpreterstate struct, sure :^)

sick hound
#

@brisk zenith i tried to make eval my self (with compiling step) but it isn't hard but time consuming

#

you need to implement one by one

#

actually two by two (implement compiler first than evaluator)

#

btw with PEP570 they added posonlyargs to CodeType

brisk zenith
#

hm okay. i mean, this challenge is quite tricky compared to the other ones, so it's fine if submissions take longer to come in. just take your time, there's no rush or anything

rugged sparrow
#

@gilded orchid @brisk zenith check it out. I havent layed it out into artwork yet, but the game works

#

you need to have pillow and fabulous installed

sick hound
#

is there any hacky chance that int.__mod__ could be made to use math.remainder's behavior

#

i'd assume not because C but still :X

rugged sparrow
#

@sick hound yes using ctypes

sick hound
#

you sure? i thought you could only patch python-defined methods via ctypes.pythonapi

rugged sparrow
#

youd have to mess with memory addresses manually

sick hound
#

oh fun

rugged sparrow
#

yea

grave rover
#

I have a great idea to do this but execution will be difficult

#

Yup I got it

#

Yeet

#

Wait n fuck I need compile()

crimson gust
#

It's a really weird challenge

desert garden
#

I think I might write a bytecode interpreter if I get the chance

grave rover
#

The worst part is that I'm so close

grave rover
#

For now I'll just use file imports I guess

#

I'll change it later to something ast-based with a twist :3

crimson gust
#

What if we just copy paste pypy

sick hound
#

So ast.parse uses compile internally

#

Umm

#

Is ast still allowed @brisk zenith

brisk zenith
#

sure. i mean really, anything is acceptable just as long as it's interesting and unique

sick hound
#

I just noticed something

#
>>> dis.dis('250 + 250 == 500')
  1           0 LOAD_CONST               2 (500)
              2 LOAD_CONST               1 (500)
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE
>>> dis.dis('500 == 500')
  1           0 LOAD_CONST               0 (500)
              2 LOAD_CONST               0 (500)
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE```
#

WAT

#
>>> compile('250 + 250 == 500', '', 'eval').co_consts
(250, 500, 500)```
brisk zenith
#

seems like a bug in the bytecode optimiser or something

burnt pasture
#

not exactly a bug. just a micro-optimization missed.

calm rampart
#

it's probably relatively rare to use constants with comparison expressions

#

whereas people will use them with arithmetic all the time, easier to type 22/7 than 3.142856142856142856142856142856

marsh void
#

Even though 22/7 is ok but not really pi tbh

sick hound
#
>>> compile('1 + 2', '', 'eval').co_consts
(1, 2, 3)```
#

it looks like it optimizes with basic arithmetic expressions like 250 + 250 or 1 + 2 but then doesn't get rid of the old constants

#
>>> compile('(1 + 2, 15)', '', 'eval').co_consts
(1, 2, 15, 3, (3, 15))```
#

it only actually uses the last constant there

#

the bytecode is optimized but the constants aren't

desert garden
#

There's probably some legacy reason they have to leave in the old constants

#

You could probably ask on the mailing list

grave rover
#

tfw I have a bytecode optimizer that fixes that

#

speaking of which, I need to optimize more

gleaming path
#

@rose imp please use bot commands in #bot-commands in future

rose imp
#

oops sorry I thought I was in that channel

ripe depot
#

Anyone here have experience with the python CAN package ?

sick hound
#

is the python CAN package weird, obfuscated, golfed, or generally weird?

rugged sparrow
#

@gilded orchid i finished up the pokemon thing. i just havent formated it yet. do you know any easy way to put an image as a background somewhere i can type it?

#

to make formating easier?

gilded orchid
#

I don't get what you mean?

rugged sparrow
#

like i finished onelining it, but formating it to the pokemon logo is a pain. cause its 8000 - 9000 characters

gilded orchid
#

oh right, maybe you could find a way to get a translucent overlay window of the pokemon logo

#

which editor do you use?

rugged sparrow
#

rn im using code pad text editor cause im on a chromebook

#

but if there is something online thatd be great

gilded orchid
#

Maybe you could set up an OBS window with your codepad editor and a pokemon logo, then you could look at the obs window while typing in the codepad window

rugged sparrow
#

hmm ok

gilded orchid
#

(the reason I suggested that is because I've seen someone use it to put two game windows on top of eachother, both with 50% transparency)

rugged sparrow
#

ah makes sense

ripe depot
#

@sick hound there just aren't that many examples. But I got my stuff working. It's pretty easy and sweet when it works. I was having an issue with the python libraries and the hardware drivers. I finally found the function to close my listener and shutdown the bus.

#

I'm using python to send new firmware images to micro controllers. So bootloader running on the micro. I convert the hex to binary in python , then send it across the CAN bus. Used TK library to make a little GUI. Working pretty well. Just the exe I build from it is pretty large.

gilded orchid
#

If I were to do a code art esolang could I submit it to both challenges?

grave rover
#

Finished my bytecode editor
... in Excel

gilded orchid
#

jesus christ why would you do that to yourself lmao

open ore
#

Math is fun

last locust
#

lol

marsh void
#

ok nvm

stray needleBOT
wind maple
#

@brisk zenith pls review

gilded orchid
#

is your solution just an image? I'm really confused

sick hound
#

...wtf py Traceback (most recent call last): File "C:\Users\Aaay\AppData\Local\Programs\Python\Python36\lib\runpy.py", line 193, in _run_module_as_main "__main__", mod_spec) File "C:\Users\Aaay\AppData\Local\Programs\Python\Python36\lib\runpy.py", line 85, in _run_code exec(code, run_globals) File "image (1).png\__main__.py", line 2, in <module> File "", line 2, in <module> ModuleNotFoundError: No module named 'fcntl'

#

that's on windows and I know it only works on *nix platforms

#

but... HOW

#

WTF is going on there

gilded orchid
#

how on earth did you make a python file into a png and have it not look like a garbled mess

sick hound
#

it contains __main__.py

#

but not fcntl

#
>>> dis.dis(code)
  1           0 LOAD_CONST               0 (0)
              2 LOAD_CONST               1 (None)
              4 IMPORT_NAME              0 (atexit)
              6 STORE_NAME               0 (atexit)

  2           8 LOAD_CONST               0 (0)
             10 LOAD_CONST               1 (None)
             12 IMPORT_NAME              1 (fcntl)
             14 STORE_NAME               1 (fcntl)

  3          16 LOAD_CONST               0 (0)
             18 LOAD_CONST               1 (None)
             20 IMPORT_NAME              2 (random)
             22 STORE_NAME               2 (random)

  4          24 LOAD_CONST               0 (0)
             26 LOAD_CONST               1 (None)
             28 IMPORT_NAME              3 (signal)
             30 STORE_NAME               3 (signal)

  5          32 LOAD_CONST               0 (0)
             34 LOAD_CONST               1 (None)
             36 IMPORT_NAME              4 (struct)
             38 STORE_NAME               4 (struct)

  6          40 LOAD_CONST               0 (0)
             42 LOAD_CONST               1 (None)
             44 IMPORT_NAME              5 (termios)
             46 STORE_NAME               5 (termios)

  7          48 LOAD_CONST               0 (0)
             50 LOAD_CONST               1 (None)
             52 IMPORT_NAME              6 (time)
             54 STORE_NAME               6 (time)

  9          56 LOAD_CONST               0 (0)
             58 DUP_TOP
             60 STORE_GLOBAL             7 (width)
             62 STORE_GLOBAL             8 (height)```
#

this is weird

#

it doesn't contain compile

#

or code

gilded orchid
#

how would you make a png file contain main.py?

sick hound
#

i have no idea

#

i'm guessing there's some kind of very weird compression going on here

gilded orchid
#

I don't think that's what they had in mind when they said 'code art' lmao

sick hound
#

it generates a code object with loads of names that don't appear in the file

gilded orchid
#

I can't really talk since I don't know anything about bytecode, but is it maybe an import?

sick hound
#

it's importing names and defining functions

#

all of those names have to come from somewhere

#

but they're not in the file

#

...wat

#

where on earth is main.py coming from

#

WHAT THE... HOW...

#

inspect.getsource returns code

#

it loads a code object with marshal

#

and then executes it

#

i have no idea how they put that in a png file

gilded orchid
#

@wind maple pls explain lmao

sick hound
#

and actually the code in there isn't even in the file

#

don't explain, i'm having fun figuring it out :P

wind maple
#

ok

#

it's stupid simple

sick hound
#

...zipimporter

#

you put a zip file in a png?

#

wow

#

it does contain PK

#

IT'S A ZIP FILE

#

YOU PUT A ZIP FILE IN A PNG

gilded orchid
#

how does that mean python code runs

#

if it's a zip

sick hound
#

the zip file has a main.py

gilded orchid
#

but how does the zip get decompressed

sick hound
#

i guess python does it

gilded orchid
#

also, how is the image not a garbled mess

#

?

sick hound
#

the image and zip file are completely separate

#

IEND®B`‚PK

#

IEND®B`‚ is the end of the .png file

#

PK is the beginning of the .zip file

gilded orchid
#

why does python ignore the image then, if it does decompress the zip?

sick hound
#

i don't know

#

._.

gilded orchid
#

turns out just renaming it to a zip and unzipping it gives you the code

sick hound
#

it doesn't for me

#

since it's a PNG file

#

...

gilded orchid
#

I just renamed it to image.zip

sick hound
#

...i am VERY confused

#

that doesn't work for me

wind maple
#
ava@madoka ~/example> unzip image.png
Archive:  image.png
warning [image.png]:  456 extra bytes at beginning or within zipfile
  (attempting to process anyway)
  inflating: __main__.py```works4me
sick hound
#

i'm using windows

wind maple
#

oh

gilded orchid
wind maple
#

try uh

#

7zip

sick hound
#

i already managed to do it

#

by removing the PNG from the beginning in a text editor

#

...so you put python code in a .zip file in a .png file

wind maple
#

I was considering doing more layers of dumb unnecessary obfucsation

sick hound
#

I am so confused...

gilded orchid
#

I feel like this is taking esoteric-python to a whole new level lmao

#

@wind maple do you know why the python interpreter ignores the png file and unzips the python file?

wind maple
#

yes

#

zip files are scanned from the end

#

it sees that the file ends in the zip end of archive marker and starts scanning backwards

gilded orchid
#

wow that is weird

brisk zenith
#

@wind maple that's pretty cool, i'll test it soon. :D

calm rampart
#

if you do it right, the zip file should think it's a self-extracting zip and not get any errors

#

if you just concatenate the zip to the png or whatever, some zip tools can still handle it but it's not a well-formed zip

#

so some tools can handle it and others can't

#

zip -A can fix it

#

@wind maple

#

(now i'm wondering if there's a way to put the png inside the zip)

#

nope, local file header is required to be followed directly by the data

#

i wonder if there's a way to embed the zip central directory and file data in the png as chunks instead of concatenated to the end

sick hound
#

png allows "ancillary" chunks, that decoders are meant to ignore if they don't recognize

#

so you could just make a big hzIp chunk with a zip file in it or something

#

and that should be ignored

grave rover
#

@gilded orchid Images start at the header, Zip files at the footer

#

Python checks the footer first if it doesn't end in .py[cod]?

#

If it's a zip it unzips it which works fine, it ignores the first data

#

Then it runs main.py

#

I think the most you can do is an image, PDF and then a zip

sick hound
#
>>> os.dup2(3,0)
>>> Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> >>>```
wind maple
#

uhhh

#

I would probably not run that 🤔

gilded orchid
#

what does that do lmao

sick hound
#

it duplicates the file descriptor 3 to stdin

#

in that case, file descriptor 3 was a file containing b'1/0\nos.dup2(5,0)\n'

#

and file descriptor 5 was a copy of stdin

tepid frost
#

Hello, can someone help me with pygame like with importing images to it

gilded orchid
gilded orchid
#
eval("""eval("print('!First£`!Second£y`!Third£qy`!Fourth£zqy`!Fifth£]zqy`!Sixth£[]zqy`!Seventh£=[]zqy`!Eighth£-=[]zqy`!Ninth£*-=[]zqy`!Tenth£&*-=[]zqy`!Eleventh£^&*-=[]zqy`!Twelfth
£%^&*-=[]zqy`')+'!','On the ')+'£','day of Christmas\nMy true love sent to me')+'%','Twelve Drummers Drumming,\n')+'^','Eleven Pipers Piping,\n')+'&','Ten Lords-a-Leaping,\n')+'*','Nine Ladies Dancing,\n')+'-','Eight Maids-a-Milking,\n')+'=','Seven Swans-a-Swimming,\n')+'[','Six Geese-a-Laying,\n')+']','Five Gold Rings,\n')+'z','Four Calling Birds,\n')+'q','Three French Hens,\n')+'y','Two Turtle Doves, and\n'+'`','A Partridge in a Pear Tree.\n\n')""".replace('+','.replace('))

I have to find an error in this

#

oh god why

scarlet osprey
#

Put it in PyCharm

#

Ctrl + Shft + L

sick hound
#

@gilded orchid look at the code that the eval is running

#
>>> print("""eval("print('!First£`!Second£y`!Third£qy`!Fourth£zqy`!Fifth£]zqy`!Sixth£[]zqy`!Seventh£=[]zqy`!Eighth£-=[]zqy`!Ninth£*-=[]zqy`!Tenth£&*-=[]zqy`!Eleventh£^&*-=[]zqy`!Twelfth
... £%^&*-=[]zqy`')+'!','On the ')+'£','day of Christmas\nMy true love sent to me')+'%','Twelve Drummers Drumming,\n')+'^','Eleven Pipers Piping,\n')+'&','Ten Lords-a-Leaping,\n')+'*','Nine Ladies Dancing,\n')+'-','Eight Maids-a-Milking,\n')+'=','Seven Swans-a-Swimming,\n')+'[','Six Geese-a-Laying,\n')+']','Five Gold Rings,\n')+'z','Four Calling Birds,\n')+'q','Three French Hens,\n')+'y','Two Turtle Doves, and\n'+'`','A Partridge in a Pear Tree.\n\n')""".replace('+','.replace('))
eval("print('!First£`!Second£y`!Third£qy`!Fourth£zqy`!Fifth£]zqy`!Sixth£[]zqy`!Seventh£=[]zqy`!Eighth£-=[]zqy`!Ninth£*-=[]zqy`!Tenth£&*-=[]zqy`!Eleventh£^&*-=[]zqy`!Twelfth
£%^&*-=[]zqy`').replace('!','On the ').replace('£','day of Christmas
My true love sent to me').replace('%','Twelve Drummers Drumming,
').replace('^','Eleven Pipers Piping,
').replace('&','Ten Lords-a-Leaping,
').replace('*','Nine Ladies Dancing,
').replace('-','Eight Maids-a-Milking,
').replace('=','Seven Swans-a-Swimming,
').replace('[','Six Geese-a-Laying,
').replace(']','Five Gold Rings,
').replace('z','Four Calling Birds,
').replace('q','Three French Hens,
').replace('y','Two Turtle Doves, and
'.replace('`','A Partridge in a Pear Tree.

')```
#

there's a random " that goes over multiple lines and doesn't ever get closed

gilded orchid
#

where? the one on the first line?

sick hound
#

yes

#

you don't have any " to end that string

#

and also inside that string you have a lot of strings that end with an actual newline instead of a \n character

gilded orchid
#

I thought I only put \n, it goes onto one line?

#

nvm turns out there was one newline

#

I'm still getting EOL while scanning string literal?

#

I changed it to:

eval("""eval("print('!First£`!Second£y`!Third£qy`!Fourth£zqy`!Fifth£]zqy`!Sixth£[]zqy`!Seventh£=[]zqy`!Eighth£-=[]zqy`!Ninth£*-=[]zqy`!Tenth£&*-=[]zqy`!Eleventh£^&*-=[]zqy`!Twelfth£%^&*-=[]zqy`')+'!','On the ')+'£','day of Christmas\nMy true love sent to me'")+'%','Twelve Drummers Drumming,\n')+'^','Eleven Pipers Piping,\n')+'&','Ten Lords-a-Leaping,\n')+'*','Nine Ladies Dancing,\n')+'-','Eight Maids-a-Milking,\n')+'=','Seven Swans-a-Swimming,\n')+'[','Six Geese-a-Laying,\n')+']','Five Gold Rings,\n')+'z','Four Calling Birds,\n')+'q','Three French Hens,\n')+'y','Two Turtle Doves, and\n'+'`','A Partridge in a Pear Tree.\n\n')""".replace('+','.replace('))
sick hound
#
eval("print('!First£`!Second£y`!Third£qy`!Fourth£zqy`!Fifth£]zqy`!Sixth£[]zqy`!Seventh£=[]zqy`!Eighth£-=[]zqy`!Ninth£*-=[]zqy`!Tenth£&*-=[]zqy`!Eleventh£^&*-=[]zqy`!Twelfth£%^&*-=[]zqy`').replace('!','On the ').replace('£','day of Christmas
My true love sent to me'").replace('%','Twelve Drummers Drumming,
').replace('^','Eleven Pipers Piping,
').replace('&','Ten Lords-a-Leaping,
').replace('*','Nine Ladies Dancing,
').replace('-','Eight Maids-a-Milking,
').replace('=','Seven Swans-a-Swimming,
').replace('[','Six Geese-a-Laying,
').replace(']','Five Gold Rings,
').replace('z','Four Calling Birds,
').replace('q','Three French Hens,
').replace('y','Two Turtle Doves, and
'.replace('`','A Partridge in a Pear Tree.

')```
#

if you want the string to contain the actual text \n instead of a newline you need \\n

#

also... what on earth are you doing?

gilded orchid
sick hound
#

why do you have an extra eval in the eval?

gilded orchid
#

so I can do `.replace('+','.replace')

sick hound
#

the first eval is enough to let you do that

gilded orchid
#

wait how would I do it with one eval?

#

because then the .replaces would have to be a string

#

which would only be possible if an eval was inside another eval?

sick hound
#

...no

#

why do you need two evals?

#

you can do one eval that converts + into .replace(

#

and then that's all you need

#

what's the second one for???

gilded orchid
#

oh wow I'm dumb, nvm lol

#
On the First daTwo Turtle Doves,
 of Christmas
MTwo Turtle Doves,
 true love sent to me
`On the Second daTwo Turtle Doves,

seems correct 🤔

gilded orchid
#
eval("""print('!First£`!Second£3`!Third£23`!Fourth£123`!Fifth£]123`!Sixth£[]123`!Seventh£=[]123`!Eighth£_=[]123`!Ninth£*_=[]123`!Tenth£&*_=[]123`!Eleventh£^&*_=[]123`!Twelfth£%^&*_=[]123`')+!','On the ')+£',' day of Christmas\\nMy true love sent to me\\n')+%','Twelve Drummers Drumming,\\n')+^','Eleven Pipers Piping,\\n')+&','Ten Lords-a-Leaping,\\n')+*','Nine Ladies Dancing,\\n')+_','Eight Maids-a-Milking,\\n')+=','Seven Swans-a-Swimming,\\n')+[','Six Geese-a-Laying,\\n')+]','Five Gold Rings,\\n')+1','Four Calling Birds,\\n')+2','Three French Hens,\\n')+3','Two Turtle Doves, and\\n')+`','A Partridge in a Pear Tree.\\n\\n')""".replace('+',".replace('"))

AttributeError: 'NoneType' object has no attribute 'replace'?

#

nvm I got it

sick hound
#

print(...).replace

marsh void
#

^

#

print returns None lol

#

Hey guys, what about "weirdest while True loop definition"? For example,

while not False:
    ...
while [x for x in range(1)]:
    ...
while bool(1):
    ...
gilded orchid
#

not esotericey enough i'd say

marsh void
#

@gilded orchid your suggestions? :)

sick hound
#

@marsh void ```py

bool([].append('python'))
False```

#

append returns None lol

marsh void
#

oops

#

Oki rewritten

sick hound
#
while __build_class__:
    ...```
marsh void
#

LOL

#

good stuff

#
while type((-1)**(1/2)) is complex:
    ... #I am outta ideas
sick hound
#
import sys

def trace(frame, event, arg):
    if event == 'line':
        if frame.f_code.co_code[frame.f_lasti]==116 and frame.f_code.co_names[frame.f_code.co_code[frame.f_lasti+1]]=='_begin':
            frame.f_lineno += 1
            trace.start = frame.f_lineno
        elif frame.f_code.co_code[frame.f_lasti]==116 and frame.f_code.co_names[frame.f_code.co_code[frame.f_lasti+1]]=='_end':
            frame.f_lineno = trace.start
    return trace

sys.settrace(trace)

def test():
    _begin
    print('Hello!')
    _end

test()```
#

@marsh void how about that?

#

there's no while loops in it but print('Hello!') still gets executed forever

#

and you can't do break or continue

desert garden
#

smh using sttrace slows everything down loads

#

Use some bytecode manipulation and just replace _end with a jump to the _begin

#

And replace _begin with some nops

marsh void
#

mhm

#

@sick hound cool tho

last locust
#

Literally just realised you can enumerate a dict to get the ‘index’ of each key:value pair.

Decided to make a search dict by index because why not? lol

#

and yes I know there’s other ways which are less lines aka list(dict.items())[index_to_get] but just interesting that you can do it like this too (and my method actually stores the index as well, rather than just doing list[index])

marsh void
#

Well yeah

marsh void
#

Hey pythoners, so our main friends are lambda, map, zip, reduce?

gilded orchid
#

for one-liners, I'd say lambdas, list comprehension and maybe short circuiting are the most important

#

for golfing i'd say eval is most important

marsh void
#

what’s golfing?thinkingglare

#

@gilded orchid ^

sick hound
#

making code as short as possible

gilded orchid
#

Doing something in as little characters as possible

#

It's called code golfing because you try to get as low a score as possible in golf

sick hound
#

try golfing the definition of "golfing"

#

"DoThingMinLen"

#

that's what code golf is, golfed

bleak juniper
#

why say lot word when few word do trick

sick hound
#

we move OT?

gilded orchid
#

Example:```python
eval("""print('!First£!Second£3!Third£23!Fourth£123!Fifth£]123!Sixth£[]123!Seventh£=[]123!Eighth£_=[]123!Ninth£_=[]123!Tenth£&*_=[]123!Eleventh£^&=[]123!Twelfth£%^&*_=[]123'+!','On the ')+£',' day of Christmas\nMy true love sent to me\n')+%','Twelve Drummers Drumming,\n')+^','Eleven Pipers Piping,\n')+&','Ten Lords-a-Leaping,\n')+*','Nine Ladies Dancing,\n')+','Eight Maids-a-Milking,\n')+=','Seven Swans-a-Swimming,\n')+[','Six Geese-a-Laying,\n')+]','Five Gold Rings,\n')+1','Four Calling Birds,\n')+2','Three French Hens,\n')+3','Two Turtle Doves, and\n')+`','A Partridge in a Pear Tree.\n\n'))""".replace('+',".replace('"))

The 2200 character lyrics of 12 days of christmas cramed in 606 characters
marsh void
#

wow cool

#

that stuff is hella unreadable tbh, or at least I’m not used to it as for now

#

But yeah, after second reading through, starts to make sense lol

snow beacon
#

Fortunately, the kind of code you golf isn't the type you need to maintain later.

marsh void
#

Yeah, fortunately FlamesLUL

marsh void
#

Technically with eval you can one-line everything

gilded orchid
#

yeah but that kind of defeats the point of oneliners

brisk zenith
#

i usually dislike the use of eval like that when golfing

fast torrent
#

@brisk zenith damn pure-ist

#

Nobody cares

vague gust
#

i care

marsh void
#

real drama is about to start lol

desert garden
#

eval is a cheaty golf

#

Most things you can do with eval you can do with clever tricks too

mortal ingot
#

i've seen exec used quite a lot, esp in py 2

marsh void
#

hm

tepid glacier
#

I've used it a few times for edge cases

#

Like for codingame challenges where multiple inputs are required a,b,c=eval('input(),'*3)

marsh void
#

well, in that case, it's ok

#

(at least in my opinion)

sick hound
#
>>> 'hello world'''
'hello world'```
marsh void
#

Weird lol

#

But understandable, since it most likely prints('hello world') then scans and finds ''

#

Yeah it does

gilded orchid
#
>>> 'a''b''c'
'abc'

turns out you don't need to use + to add string together

tropic gulch
#

just a combined string literal, 'hello world' and '' - if you directly write multiple string literals after another, they get interpreted as single string, which allows you to e.g. switch quotes or f-/r-strings without an explicit concatenation

nocturne saddle
#

It's also useful if your lines get too long

marsh void
#

yeah

nocturne saddle
#
my_string = (
    "this will all "
    "be one string"
)
sick hound
#
>>> print('this is a very '
... 'long string')
this is a very long string```
marsh void
#

wait ellipsis lol

nocturne saddle
#

REPL

marsh void
#

but yeah, it’s cool that it works like that

sick hound
#

just python repl

marsh void
#

yeah k

tropic gulch
#

though even is you write a +, the interpreter will optimize it to a single literal

#
>>> dis.dis("'hello''world'")
  1           0 LOAD_CONST               0 ('helloworld')
              3 RETURN_VALUE
>>> dis.dis("'hello'+'world'")
  1           0 LOAD_CONST               2 ('helloworld')
              3 RETURN_VALUE
marsh void
#

What is that though?

tropic gulch
#

bytecode disassembly

#

but I wonder what that 0 vs 2 in the second to last column means

sick hound
#

it's the actual argument in the bytecode

#

for LOAD_CONST, it's the index of the constant in the list of constants stored internally in the code object

calm rampart
#

@tropic gulch because it still compiles constants for the original strings

#
>>> compile("'hello'+'world'",'','eval').co_consts
('hello', 'world', 'helloworld')``` doesn't do it for me in 3.7, but does in 3.6.6
#

I think I saw someone complaining about that a few days ago, idk if it was in here or on a mailing list

tropic gulch
#

🤷

marsh void
#
class LOL:
    def __init__(self):
        pass
    def __hash__(self):
        return hash(self)**2
lol = LOL()
hash(lol)
#

oh man why this code isn’t working? what is that weird RecursionError?

bleak juniper
#

you've accidentally made your __hash__ method recursive, since doing hash(self) will call __hash__, so your method just continually calls itself until you run out of memory

#

@marsh void

marsh void
#

Yeah I know, decided to do it as a joke but failed lol

gilded orchid
#

Is there a way to update an something in a list variable using global.update()?

#

globals().update({aList[2]:3}) something like this

brisk zenith
#

well, globals["list_name"][2] = 3

#

or, globals["list_name"].__setitem__(2, 3) i believe

gilded orchid
#

oh ok, thanks

grave rover
#

Got running Lua in Python working, yeet

#

I also got python in lua working 👀

sick hound
#

does that mean you can run python in lua in python?

grave rover
#

Yes

#

And Lua in python in lua in python

#

Not much of a point though since both Lua instances share the same runtime, same with python

gilded orchid
#
a=[0,1]
eval('a+=sum(a[-2:])\n'*31)
'\n'.join(a)

Why doesn't this work as a golf for the fibonacci sequence

#

It gives a SyntaxError

sick hound
#

eval evaluates an expression

#

2+2 or print("hello") are expressions

#
a+=sum(a[-2:])``` is not an expression
#

use exec instead

#

@gilded orchid

gilded orchid
#

then I get:TypeError: 'int' object is not iterable

sick hound
#

what's your code?

gilded orchid
#
a=[0,1]
exec('a+=sum(a[-2:])\n'*31)
'\n'.join(a)
sick hound
#

sum(a[-2:]) is an integer

#

you can't add an integer to a list

grave rover
#

you can do a+=[sum(...)]

marsh void
#

Is using phi formula and listcomp for it considered inefficient?

marsh void
#
phi = (1+5**0.5)/2; [int((phi**n-(1-phi)**n)/(5**0.5)) for n in range(10)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

not golfing, but still pretty math beautiful

marsh void
#
[x for x in range(2, a+1) if not any(x % y is 0 for y in range(2, int(x**0.5)+1))]

gets all prime numbers up to a
what do you guys think about this?

desert garden
#

Too much whitespace

#
[x for x in range(2, a+1)if~any(x%y==0for y in range(2,int(x**0.5)+1))+2]
#

Can invert all the checks for ```py
[x for x in range(2,a+1)if all(x%y for y in range(2,int(x**0.5)+1))]

marsh void
#

Oki

#

Thanks

sick hound
#

you can also use .5 instead of 0.5

#
[x for x in range(2,a+1)if all(x%y for y in range(2,int(x**.5)+1))]```
marsh void
#

heh well, is it the shortest one?

sick hound
#

is what the shortest what

topaz anchor
#

no it's not

#

you can shave off a lot by simply decreasing performance

marsh void
#

Yeah well

#
[x for x in range(2,a+1)if all(x%y for y in range(2,int(x**0.5)+1))]

so is this one kind of the best in terms "short and efficient"?

gilded orchid
#

why did you need the int() in the range at the end?

#

you could just do x**.5+1

last locust
#

range arguments have to be an int

gilded orchid
#

yeah but it'd be an int even if the int() isn't there

last locust
#

It wouldn’t?

gilded orchid
#

oh, well he could still just use brackets

#

(x**.5)+1

last locust
#

Nope

#

Makes no difference with brackets since it does ** first anyway

#

@gilded orchid

gilded orchid
#

that would be correct though

last locust
#

Not an int though

gilded orchid
#

oh yeah, nvm I'm dumb

marsh void
#

Lol

desert garden
#

Is there a shorter alternative to ~<...>+2 for negation?

#

Using a tilda had the advantage of removing any whitespace around not, but iirc there's a shorter way I can't remember

tropic gulch
#

huh, that isn't python, is it?

desert garden
#

It is

#

~ is a bitwise inverse

#

So True goes to -2 and False to -1

#

Then if you +2 it it's essentially negated the boolean

#

By putting the +2 at the end not the start you can minimize leading whitespace

tropic gulch
#

ah, so <...> isn't part of the syntax but just your placeholder, got it

#

if it's really just True and False as input x, how about 1-x?

brisk zenith
#

.. does -x not work?

tropic gulch
#

-True is still -1, -False is still 0

brisk zenith
#

ohh i misunderstood the question, my bad.

wind maple
#

x^1

marsh void
#

True^1 is 0, False^1 is 1

marsh void
#

So I guess it’s the best one

winged onyx
#

how does matplotlib work? eg. you need to assign stuff to variables for them to actually work (but the variables are not attached to anything), otherwise that line does nothing

(eg. making an animated graph, something something FuncAnimation but i havent used matplotlib in some time)

snow beacon
#

Could you give an example of the weirdness? Are you sure you don't use the variable later?

winged onyx
#

yes

#

i remember doing a graph thing for the last AoC
animation or not it relied on a variable assignment (literally just a = some_code_i_forgot)

snow beacon
#

It could be to do with reference counting and garbage collection

gilded orchid
#

If you have to store lots of text in a code golf, is there a simple way to compress and decompress it to save characters?

grave rover
#

It depends

#

Sometimes there's an easy way to do it (for long text use b64 encoding or something) but other timesx you'll have to be real creative

desert garden
#

@marsh void thanks that's the one I was thinking off

#

Has the advantage of not leading with a number so you can avoid whitespace

marsh void
#

Yeah, Ava was the first though >.>

#

Also, kinda not esoteric, but I was wondering, is it ok to use ; structures in packages?
for instance, in decorators:

def benchmark(function):
    def decorator(*args, **kwargs):
        import time; start = time.perf_counter()
        res = function(*args, **kwargs); end = time.perf_counter()
        estimated = (end-start)*1000; print(f"Executed function {function.__name__}(*args, **kwargs), estimated time: {estimated:.2f}ms.")
        return res
    return decorator
vocal oyster
#

what would be the benefit of that?

marsh void
#

There are no benefits, just it’s more comfortable for me to write some lines like that

brisk zenith
#

but it's far less comfortable for us to read, so don't :D

gilded orchid
#

Do semicolons function identically to new lines?

marsh void
#

yeah

#

Ok got y’all

marsh void
#

Also what do you think about "black" code style?

brisk zenith
#

@gilded orchid no, you can't indent after them

gilded orchid
#

oh ok

brisk zenith
#

there are some cases where semicolons just can't be used

gilded orchid
#

I was just gonna use it to replace \n in some of my evals in code golfs

brisk zenith
#

well yeah you can in places

gilded orchid
#

[print(i)for i in range(51)if any([map(int,bin(i)[2:]%a for a in(2,i))])^1] gives SyntaxError: Generator expression must be parenthesized

#

what does that mean?

#

(for context, I'm trying to print all the pernicious numbers from 0 to 50)

sick hound
#

it means you need to put parentheses (( and )) around a generator expression

#
map(int,bin(i)[2:]%a for a in(2,i))```
#

@gilded orchid

#

also what is a pernicious number

gilded orchid
#

'A pernicious number is a positive number where the sum of its binary expansion is a prime number.'

sick hound
#

oh

gilded orchid
#

I currently have got

[print(i)for i in range(1,51)if all([sum(map(int,bin(i)[2:]))%a!=0for a in range(2,i)])]

but it isn't working

#

something wrong in my prime number checker but idk what

sick hound
#

you're checking between 2 and i

#

the sum of the binary expansion of the number is less than i