#esoteric-python

1 messages · Page 80 of 1

hollow patrol
#

Oh I see

#

The Function supplied it

#

@formal sandal Make it work with yields.

#

Also where did you get z

#

Also, r.assign should use kwargs

#

That's really interesting

#

Keep it up

#

If you get it to work with yield, you should use this for async lambdas

#
def nsync(f):
    @functools.wraps(f)
    async def wrapper(*args, **kwargs):
        call = f(*args, **kwargs)
        i = next(call)
        try:
            while True:
                i = call.send(await i)
        except StopIteration as e:
            if len(e.args) > 0:
                return e.args[0]
            else:
                return
    return wrapper```
formal sandal
#

Maybe I'll make it work with yield some day

hollow patrol
#

Ok

#

If you want @formal sandal , I can DM you a link to my source so that you can build on it or improve it

#

Or add some of it to yours

formal sandal
#

I think it would be more interesting if I do it on my own :)

formal sandal
pure dew
#

wat

formal sandal
proper vault
#

do [] work?

formal sandal
#

Not yet, I'm going to add these now

proper vault
#

cool

formal sandal
#

Sadly, I can't really use , as input :(

#

Or maybe I can

#

wait

gilded orchid
#

what's the shortest way to do an 8bit wrapping thing for brainfuck? (eg: if it's -1 then change it to 255, if it's 256 change it to 0, else keep it the same)

#
[[n,0],[255]][n<0][n>255]```
#

I think this would work but it's kinda dumb

#

wait I just realised

#
>>> n = -1
>>> n%256
255
>>> n=256
>>> n%256
0
#

wow

sick hound
#
_try = lambda try_clause, except_clause, catch=Exception: type("nested", (), {"__init__": lambda self, *ctx: [setattr(self, "ctx", ctx), None][1],"__enter__": lambda self, *ctx: [[ctx.__enter__() for ctx in ctx], None][-1],"__exit__": lambda self, *args: [[ctx.__exit__(*args) for ctx in self.ctx], None][1]})(type('Handler', (), {'__enter__': lambda self: None,'__exit__': lambda self, et, ev, tb: et is not None and issubclass(et, catch) and (except_clause(ev), True)[1]})(),type('Body', (), {'__enter__': lambda self: None,'__exit__': lambda self, et, ev, tb: try_clause()})())

this is suppost to catch errors by abusing context protocal but its not catching anything when i do, I get no error in the console either

_try(lambda: (_ for _ in []).throw(Exception), lambda e: print(e)).__enter__()
#

Pls ping me if you can help or have suggestions

marsh void
#

is there a way to uhm, fetch the function object from FrameInfo? (in inspect.stack())

brazen geyser
#

FrameInfo should have the name of the function

#

and then you can use that with either f_locals or f_globals to get it

#

might be a little more difficult for modules and stuff

lament ibex
#

!e

import inspect
a = lambda: inspect.stack()
res = a()[0]
print(type(lambda: None)(res.frame.f_code, res.frame.f_globals, res.function))
night quarryBOT
#

@lament ibex :white_check_mark: Your eval job has completed with return code 0.

<function <lambda> at 0x7fcb12a7b4c0>
lament ibex
#

lol idk seems to work for lambdas

brazen geyser
#

that wouldnt be the same object

lament ibex
#

ah true

marsh void
#

so, are f_locals a copy of function's locals

#

? I wonder if I can modify function's namespaces outside of it

brazen geyser
#

f_locals is what locals returns. not a copy.

#

you can modify this dict however it might not always work as excepted, because the compiler cant always discern your intentions and produce the correct instructions

#

you can add a new name to f_locals, provided it's not already in the local scope.
but there wont be much point as you cant access it, since the generated instructions will try to look for the name in the global scope.

if the name is already in the local scope then trying to change the value associated with that name in f_locals wont do anything.

formal sandal
#

!e

g = (locals()['.0'] for x in [2, 3, 5])
for i in g:
  print(i)
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

001 | <tuple_iterator object at 0x7fb3933cc280>
002 | <tuple_iterator object at 0x7fb3933cc280>
003 | <tuple_iterator object at 0x7fb3933cc280>
formal sandal
#

Yep

#

I doubt this can be useful, though.

snow beacon
#

@sick hound this might be the wrong channel for that. Try an offtopic one.

#

@sick hound you only run the body function when _try(...).__exit__ is called. If you want to use it as a context manager in a with block, it can't catch errors in its own __exit__.

rugged sparrow
#

@sick hound I have written something similar, there is a class called ContextDecorator that concerts a context manager into a decorator and allows that to work

calm rampart
#

@gilded orchid there's always n & 255

marsh void
#

Hey everyone

#

why would this fail?

def f():
    locals().update(x=10)
    return x
f()```
#

yeah, got it

gilded orchid
#

isn't it because locals().update doesn't work in functions

marsh void
#

python thinks of x as a global variable

#

am I right?

gilded orchid
#

I don't actually know why it doesn't work

marsh void
#

more specifically, locals().update doesn’t work with functions

snow beacon
#

Locals are immutable in functions, I thought.

gilded orchid
#

I just remember someone making a super janky work around for a lambda I made a while ago

marsh void
#

At function scope (including for generators and coroutines), [this function] returns a dynamic snapshot of the function's local variables and any nonlocal cell references. In this case, changes made via the snapshot are not written back to the corresponding local variables or nonlocal cell references, and any such changes to the snapshot will be overwritten if the snapshot is subsequently refreshed (e.g. by another call to locals()).

#

!pep 558

night quarryBOT
#
**PEP 558 - Defined semantics for locals()**
Status

Draft

Python-Version

3.9

Created

2017-09-08

Type

Standards Track

marsh void
#

^ here

#

@gilded orchid I would like to have a look if I can, haha. Please don’t tell me you used ctypes, though.

gilded orchid
#

nah I didn't make it

marsh void
#

lol alright

gilded orchid
#
a=lambda x:(locals().update({'hello':'test'}),print(locals()['hello']))```
I think this was it
marsh void
#

yeah that’s bad

#

alright

#

!eval
a = {}
import('ctypes').py_object.from_address(id(a)).value = {'a': 1}
print(a)

night quarryBOT
#

@marsh void :white_check_mark: Your eval job has completed with return code 0.

{}
marsh void
#

oh I forgot how to do this lol

snow beacon
#

Is forbiddenfruit on the snekbox?

hollow patrol
#

I'm working on something called lambdatools, which is pretty ecoteric.

#

Nekit is helping me out with some of it.

#

Here's an example for some of you folks

#
    import asyncio

    async def coro(x):
        print(x)

    coro2 = nsync(function('x', lambda v: ( #create an async lambda with a parameter x
        (yield coro(v.x)), #await coro(x)
        result(v.x ** 2) #return x ** 2
    )))


    out = asyncio.run(coro2(5))```
#

That's an async lambda coroutine.

#
    factorial = function('x', lambda v: ( 
        when(lambda v: v.x == 1, lambda v: (
            result(1)
        )),
        result(v.x * v.__ref__(v.x - 1))
    ))```
#

This is a lambda which references itself

#

So yeah

proper vault
#

@snow beacon yes

brazen geyser
#

locals().update works in that particular case

marsh void
#

yeah I get it

#

so I am not sure how we can make that work

brazen geyser
#

eval('x', locals())

#

:p

#

there really isn't much of a way to make it work aside from patching bytecode

marsh void
#

wait real shit no?

#

oh I mean lol

brazen geyser
#

you just have to change that instruction to LOAD_NAME or LOAD_FAST

marsh void
#

I thought you can insert that stuff

#

I mean

#

nevermind

#

!eval
def f():
exec('x = 10', locals())
return x
f()

night quarryBOT
#

@marsh void :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 4, in <module>
003 |   File "<string>", line 3, in f
004 | NameError: name 'x' is not defined
marsh void
#

yikes

hollow patrol
#

!e
def f():
exec('x = 10', globals())
return x
f()

night quarryBOT
#

@hollow patrol :warning: Your eval job has completed with return code 0.

[No output]
hollow patrol
#

@marsh void Like that maybe?

night quarryBOT
#

@brazen geyser :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 16, in <module>
003 | TypeError: an integer is required (got type bytes)
brazen geyser
#

this works in 3.7 but not in 3.8

#

not sure why. the error doesn't help much either.

#

line 16 is new_code_object = CodeType(

#

ah, there's a new param. posonlyargcount.

#

!e

from dis import opmap
from types import CodeType


def f():
    locals()['x'] = 10
    return x


old_code_object = f.__code__

bytecode = bytearray(old_code_object.co_code)
bytecode[10] = opmap['LOAD_FAST']
bytecode[11] = 0

new_code_object = CodeType(
    old_code_object.co_argcount,
    old_code_object.co_posonlyargcount,
    old_code_object.co_kwonlyargcount,
    old_code_object.co_nlocals,
    old_code_object.co_stacksize,
    old_code_object.co_flags,
    bytes(bytecode),
    old_code_object.co_consts,
    old_code_object.co_names,
    ('x',),
    old_code_object.co_filename,
    old_code_object.co_name,
    old_code_object.co_firstlineno,
    old_code_object.co_lnotab,
    old_code_object.co_freevars,
    old_code_object.co_cellvars,
)

f.__code__ = new_code_object
print(f())
night quarryBOT
#

@brazen geyser :white_check_mark: Your eval job has completed with return code 0.

10
zealous widget
#

leave this here, from python-discussion:

In [78]: class Direction:
    ...:     North = East = South = West = e

In [79]: Direction.North
Out[79]: 0

In [80]: Direction.East
Out[80]: 1

In [81]: Direction.South
Out[81]: 2
#

@brazen geyser is there a way to do this outside of a class

brazen geyser
#

not that im aware of

#

btw i thought a bit more about your eint implementation with individual descriptor instances

#

can definitely see some use cases

#

e.g. enums where you dont want their value ranges to overlap

zealous widget
#

i thought of a use for it currently, it's not necessary, but i want to give it a go anyway

#

it's for the code-jam qualifier, but i can use more general desciptions:

class Token:
    def __init__(self, parse_this):
        self.parse_this = iter(parse_this)
    def __set_name__(self, owner, name):
        setattr(owner, name, next(self.parse_this))
#

it's odd, but i can just keep setting some attribute = token to get the next item

#

seems unnecessary but also real simple once it's set up

#

i assume i'll need some try/except block for StopIteration

zealous widget
#

doesn't seem to work inside class methods

brazen geyser
#

oh huh

#

thats pretty interesting

#

you get access to the descriptor object directly

#

nothing happens if you assign it from anywhere outside the class definition body it seems

#

think that might be a bug actually

#

or oversight

#
>>> class D:
    def __set_name__(self, owner, name):
        print(owner, name)
    def __get__(self, instance, owner):
        return 22
    def __set__(self, instance, value):
        print(value)

>>> class Test:
    pass

>>> Test.d = D()
>>> test = Test()
>>> test.d
22
>>> test.d = 324
324
>>> 

so __get__ and __set__ still work as expected. it's just __set_name__ that gets left behind.

#

ah there's a blurb about this in the docs

#

https://docs.python.org/3/reference/datamodel.html#object.__set_name__

Note __set_name__() is only called implicitly as part of the type constructor, so it will need to be called explicitly with the appropriate parameters when a descriptor is added to a class after initial creation:
class A:
   pass
descr = custom_descriptor()
A.attr = descr
descr.__set_name__(A, 'attr')
#

not sure why it's this way

#

seems like it'd be trivial to update class objects' default setattr behaviour to handle this.

#

but i suppose it wouldnt be worth the overhead

zealous widget
#

it's a lot to keep track of for me, i might mess with it more later

brazen geyser
#
>>> class Descriptor:
    def __set_name__(self, owner, name):
        print(owner, name)

>>> class AutoSetName(type):
    def __setattr__(cls, name, value):
        super().__setattr__(name, value)
        try:
            value.__set_name__
        except AttributeError:
            pass
        else:
            value.__set_name__(cls, name)

            
>>> class Test(metaclass=AutoSetName):
    pass

>>> Test.descriptor = Descriptor()
<class '__main__.Test'> descriptor
>>> 

metaclasses to the rescue

zealous widget
#

name checks out

marsh void
#

!e
try:
exit()
except:
print(13)

night quarryBOT
#

@marsh void :white_check_mark: Your eval job has completed with return code 0.

13
marsh void
#

lol what

#

!e
class H:
pass
raise H()

night quarryBOT
#

@marsh void :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 3, in <module>
003 | TypeError: exceptions must derive from BaseException
marsh void
#

eh

grizzled cloak
#

@thin trout does this count?

def lemon():
    try:
        return 'AI'
    except:
        return 'Too sour!'

co_consts = list(lemon.__code__.co_consts)
co_consts[1] = 'way too sour!'
new_lemon = types.CodeType(lemon.__code__.co_argcount,
                             lemon.__code__.co_kwonlyargcount,
                             lemon.__code__.co_nlocals,
                             lemon.__code__.co_stacksize,
                             lemon.__code__.co_flags,
                             lemon.__code__.co_code,
                             tuple(co_consts), 
                             lemon.__code__.co_names,
                             lemon.__code__.co_varnames,
                             lemon.__code__.co_filename,
                             lemon.__code__.co_name,
                             lemon.__code__.co_firstlineno,
                             lemon.__code__.co_lnotab,
                             lemon.__code__.co_freevars,
                             lemon.__code__.co_cellvars)

lemon.__code__ = new_lemon
lemon()
Out[68]: 'way too sour!'
thin trout
#

Hmmm 🙃

#

Let's say it does count :)

#

Pretty cool solution!

grizzled cloak
#

return doesnt call any functions right?

thin trout
#

Call a function? roothink

grizzled cloak
#

yeah like something called __on_return__ haha

thin trout
#

But how would you return from __on_return__ if everytime you return it call __on_return__? roothink

grizzled cloak
#

uhhhhh

#

hahahah

hollow patrol
#

Maybe...

#

raise ReturnError(result)?

brazen geyser
#

though if you were to interpret return doesnt call any functions right? flexibly,
return could result in a function call if a trace function is set via sys.settrace

grizzled cloak
#

Yeah I would need return something to call a function on something, so that function can raise a error

snow beacon
#

You could process the bytecode to change all the returns

formal sandal
#

click is very cool

thin trout
#

The first gif doesn't load :(

formal sandal
#

You can click on it and the press "open original"

#

I have no Idea how to unattach the gif...

#

got it

#

Doesn't load for me either in discord, but as a standalone file it works

marsh void
#

yeah, haha

#

b.at(2).at(1)

#

what is stekk lol

#

stack-based python-like thing?

formal sandal
#

Yeah.

#

Because if you have a multidimensional array, you will have this with []:

array[0][1][2][3]

But:

array:0:1:2:3
thin trout
#

Pretty cool!

formal sandal
#

The console module I wrote is itself code gore...

#

Its maximum indentation level is 7

marsh void
#

code gore ain't cool heh

formal sandal
#

true

#

I will try to refactor that spaghetti diarrhea now...

#

After finishing the greeting ASCII art, of course.

formal sandal
#

On-the-fly autocompletion!

#

If you just press tab, the console will print you all the possible names that start with the given substring.

#

Then you can type more letters, and it will dynamically adjust the list

#

I probably have to add a space before the list to make it work for terminals or humans that don't support color.

formal sandal
snow beacon
#

How do brackets work? Do they do something to the stack?

formal sandal
#

Yep.

#

I will post a tutorial soon.

#

Brackets denote a 'stack expression'.

#

So if you write (1 2 3 4 5), numbers 1, 2, 3, 4, 5 will be pushed onto the stack.

#

.func denotes a function call. It can be either a standalone expression or a command inside a stack expression.

#

So these are equivalent:

("hello " .print "world!" .println)

("world!" "hello " .print .println)
#

When the stack expression 'ends', the top element is popped from the stack to become the result of a stack expression.

#

If you mean [] not (), that's just a list.

rugged sparrow
#

@formal sandal if you want to make the autocompletion more human friendly, put it on the line below input and put the diff possibilities between [], ex [ opt1 opt2 opt3 ]

#

That way it’s clear on terminals without color and shitty spacing

pure dew
#

^ I second this

subtle island
#

IDK if this is the right place for this, but it's metaprogramming and I'm not sure where else this would go. I'm consuming some API's using Quicktype.io to generate dict to object classes and want to generate str and repl functions for these classes dynamically. (Full class code here https://app.quicktype.io?share=OhSj0FUBrFsWJ7P94BoD)

I've written a function that will eventually be a metaclass or class decorator, that returns source code for each class based on inspection, but I can't figure out how to bind the string source code to an actual function.

def str_wrap(cls):
    params = list(inspect.signature(cls).parameters.keys())
    new_params = []
    for param in params:
        param = 'self.' + param
        new_params.append(param)
    values = ', '.join(new_params)
    new_str = "{}({})".format(cls.__name__, values)
    cls.__str__ = new_str
#
Instrument.__str__
'Instrument(self.asset_type, self.cusip, self.description, self.symbol)'
#

But the method isn't actually callable.

#

cls.__str__ = classmethod(new_str) doesn't seem to do the trick either.

crystal mica
#

Did you try py setattr(cls, '__str__', new_str)

whole kiln
#

Isn't new_str just a string?

crystal mica
#

Oh it is?

#

You are right it is

whole kiln
#

Looks like it

#

I think something like this will work, if it is really this simple ```py
def str(self):
return "abc"
cls.str = str

crystal mica
#
    new_str = lambda cls: "{}({})".format(cls.__name__, values)
    cls.__str__ = new_str```perhaps?
#

Hmm it might raise error for values in that case, will need to test

#

But the idea is that it should be a callable

subtle island
#

Yea, I was watching pycon vid from Cookbook author that showed how to do that, I may have to go rewatch

#

was using metaclasses but I don't recal how he got the eval() calls in there.

#

I promise a blog post once I get it figured out.

#

Best I can get is <bound method ? of <class 'cls'>

#
def str_wrap(cls):
    params = list(inspect.signature(cls).parameters.keys())
    new_params = []
    for param in params:
        param = 'self.' + param
        new_params.append(param)
    values = ', '.join(new_params)
    new_str = "{}({})".format(cls.__name__, values)
    setattr(cls, '__str__', classmethod(new_str))

str_wrap(Position)
Position.__str__
whole kiln
#

That's not how classmethod is used

#

It's typically used as a decorator, and it needs an existing function given to it

#

I don't believe it's needed here regardless

#

See above examples for how to do this

crystal mica
#

Here

#
import inspect

def str_wrap(cls):
    params = list(inspect.signature(cls).parameters.keys())
    new_params = [f"self.{param}" for param in params]
    values = ', '.join(new_params)
    __str__ = lambda self: "{}({})".format(cls.__name__, values)
    cls.__str__ = __str__

class A:
    def __str__(self):
        return 'No.'

a = A()
print('Before:', a)

str_wrap(A)

a = A()
print('After:', a)```
night quarryBOT
#

@crystal mica :white_check_mark: Your eval job has completed with return code 0.

001 | Before: No.
002 | After: A()
crystal mica
#

Same idea Mark had, it has to be a callable, accepts a self, and returns a string

subtle island
#

Thanks. I need to make a test for this. I'm still getting 'str' object not callable, but out of time for tonight.

#

I want to make this a class decorator or metaclass at some point, but it's more of an intellectual exercise for now.

formal sandal
#

Hi everyone, I made a tutorial on basics and conditionals in stekk (my stack-oriented toylang), maybe you could take a look? (if I haven't annoyed you to death yet, of course!)
https://github.com/decorator-factory/stekk // tutorial folder

snow beacon
#

It's very cool. I didn't realise there was such a balance of nested expressions and statements that use the stack. I'm excited to see how the code block idea develops further.

formal sandal
#

Wait till you see the actual code that does something! It looks absolutely horrible.

#
get := {
  __get_result := $N;
  (
    .swap
    .--
    {(
        ()#0  (.dup)#$lvalue#$name (.over)#$expr
        .rot .drop .swap .rot .over .over .=
        .if () {
            .rot;
            __get_result := ();
        } else {
            (.rot .swap .drop);
        })
    }
    .foreach
  );
  __get_result
};
sick hound
#

lol

#

that is great

formal sandal
#

This is a function that allows you to use code blocks as associative arrays... kinda.

sick hound
#

@formal sandal btw instead of with open, parser = Lark() thingy you can just use Lark.open

#

with rel_to=__file__

formal sandal
#

oh

#

I will probably rewrite/refactor most of the thing some day because some places are just spaghetti monsters.

#

It's challenging to make even basic functions because there are no 'local variables'

#

So if anyone decides to name their variable __get_result, they are screwed the second they use get.

#

Maybe I can do some giant brain trick to get rid of that variable, but that will be even worse than .rot .drop .swap .rot .over .over

#

The program looks like a transcript of some rap song

proper vault
#

just make __name reserved

formal sandal
#

What do you mean?

sick hound
#

to much walrus

proper vault
#

in python, if someone were to name their variable __import__ and such, they would be screwed. It is pretty common to make __name reserved for internal usage in languages

formal sandal
#

Well, here __get_result is not an internal variable.

#

Hm... I have an idea.

#

If we ignore get (or find a trick to remove __get_result), then maybe I can make modules using dicts!

sick hound
#

Oh, I really liked usage of return annotations to represent the stack

#

I guess you can write a simple analyzer to verify them

formal sandal
#

Well, I changed that

#

I moved them to docstrings

snow beacon
#

Oh, was it like Forth convention?

formal sandal
#

Yes

sick hound
#

For side effect functions, that is a good idea to represent changes in return annotation if you can

snow beacon
#

Use ! in the name, perhaps.

formal sandal
#

Well... I don't think there's any function in stekk that doesn't have a side effect :)

snow beacon
#

Other than doing things to the stack

formal sandal
#

I mean, besides func := {}

#

Yes, good idea

snow beacon
#

Have you thought of allowing string indexing on code blocks?

formal sandal
#

Hm...

#

Maybe that makes some sense, but that's just a code block

#

Maybe I can allow overloading arbitrary operations on built-in obejcts...

snow beacon
#

What operations would there be to overload?

formal sandal
#

maybe __getitem__?

#

Like

(get {} "getitem" [""] .overload);
#

Since I don't have classes or type variables, I can just supply instances of those types...

snow beacon
#

You could have a function to alter a method on the top of stack, and the you could combine several calls into e.g. a dict function.

formal sandal
#

Or maybe

subclass := {
  __getitem__ := {"scary code here"};  
  __push__ := {
    ;; (dict [k, v] .push)
    (.bloat .swap .~assignment .swap .drop .++);
  };
}

({} .typeof subclass .embellish $N);
snow beacon
#

I don't really understand what you're overwriting.

formal sandal
#

I have a function push that appends an element to a list.

#

Then I might want to overwrite it to work with dicts.

#

Like (my_dict ["key", "value"] .push $N);

snow beacon
#

What's the {} .typeof subclass .embellish?

formal sandal
#

Well, that's a sequence of imaginary functions...

#

First, I get the type of a code block.

#

Then I give it additional behaviour defined in subclass which is a dict, i.e. codeblock defined earlier.

snow beacon
#

That affects every codeblock?

formal sandal
#

Yep. That would affect every codeblock.

#

But it will be probably a pain in the ass to implement

snow beacon
#

Like JavaScript prototypes.

#

I don't like doing things globally, myself.

formal sandal
#

Another cool thing would be to convert a stack diagram into a function.
LIke

([$a, $b, $c], [$a, $b, $c, $b, $a] .sdf)
#

Using python, it's easy

#

But I want to define it in stekk!

#

Maybe you can do this:

(3, [0, 1, 2, 1, 0] .sdf)

Then collect top 3 elements and place them according to the list.

snow beacon
#

You could allow codeblocks instead of numbers, such as {1; 0; (.+)}, where it would take the second and first and add them.

#

The semicolon separated ordinals are pushed before.sdf runs the rest.

formal sandal
#

What a meant was a function that does this:
(1 2 3 .f) -> (1 2 3 2 1)

#

So that you don't have to die trying to find another combination of drop, dup, swap, rot and over.

snow beacon
#

Oh, so not for defining whole functions, just for moving values around.

formal sandal
#

Happy esoteric new year everyone.

tropic night
#

hello guys...

#

how can you make a simple "guess my string" script, obfuscating the password so that someone in a programming course would not be able to read the code and figure it out?

#

some of the things that goes on here I cannot even follow, so maybe anyone can take the challenge for me?

#

or just give me a hint on howto so i can help out a guy in the help channel

green nymph
#

just obfuscate not encrypt?

tropic night
#

encrypt can work, but all in one file maybe...

#

how would that work?

green nymph
#

if so you can just use importlib with custom loader

tropic night
#

im not following

#

like making a new import machinery?

green nymph
#

yeah

#

write your code apply ceasar cypher or whatever to obfuscate

tropic night
#

interesting idea.. sounds very overengineered. why would that work?

proper vault
#

you could just use a hash of the string and compute the hash of the input string

green nymph
#

and in your main script decode the file and import it

proper vault
#

and compare

tropic night
#

yeah hash compare will work, but i do love the importlib idea..

#

want to write it for me @green nymph? while i do the more sensible idea of using a hash?

upbeat dove
#

http://nuitka.net/pages/overview.html
https://github.com/nuitka/nuitka

I haven't tried it myself but I heard good things.

#

Isn't exactly the question you asked for but in the help he was asking about turning it into an exe.

green nymph
#

@tropic night can try, why not

maiden blade
#

as the one who asked the question, Im as confused as I was when I was born

#

Nuitka doesnt seem to support python 3.8

#

also, what do you guys mean by "hash the string"

edgy kelp
#

I've got this thing that converts strings to bits in zero with form... so you could obfuscate the string from the user and compare it to one obfuscated by you before ​‌​​‌​​​​‌‌​​‌​‌​‌‌‌‌​​‌​​‌​​​​​​‌‌​​‌​‌​‌‌​‌​​‌​‌‌‌​‌‌​​‌‌​‌‌​​ as an example

brazen geyser
proper vault
#

a hashing function is a byte sequence -> number mapping, that assigns a unique number to each sequence, but the inverse function does not exist

#

naturally, this is impossible, but some algorithms get close enough

zealous widget
#

use a 1d reversible cellular automata on the byte string

#

that's some fun obfuscation

edgy kelp
#

maybe use hashlib instead of hash() to make sure it's unique

proper vault
#

^, the default python hash() is not a robust hashing function IIRC

#

you could just write a C extension that does a pretty simple encryption and compile it without giving anyone the source. I certainly would not look through x86 ASM to guess some random password.

green nymph
#

@tropic night


from base64 import b64decode
from pathlib import Path
from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader


class MyLoader(SourceFileLoader):
    def get_data(self, path: str) -> str:
        data = super().get_data(path)
        return b64decode(data)


if __name__ == '__main__':
    spec = spec_from_loader(
        "secret", MyLoader("secret", str(Path('.') / 'secret.py'))
    )
    secret_module = module_from_spec(spec)
    spec.loader.exec_module(secret_module)
    
    secret_module.foo()

and then put some base64 encoded python code to your secret.py

#

just to simplify without any code imports you can do that

from base64 import b64decode, b64encode
from pathlib import Path
from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader

my_code = b64encode(
    'def foo():\n    print("Hello World!")'.encode('utf-8')
)


class MyLoader(SourceFileLoader):
    def get_data(self, path: str) -> str:
        return b64decode(my_code)


if __name__ == '__main__':
    spec = spec_from_loader(
        "secret", MyLoader("secret", str(Path('.') / 'secret.py'))
    )
    secret_module = module_from_spec(spec)
    spec.loader.exec_module(secret_module)

    secret_module.foo()
tropic night
#

cool thanks @green nymph I have to look at it a bit later 😄

snow beacon
#

It's designed for code, but works with anything, really. The weird bit is that it includes the encoder in the decoder.

#

Incidentally, there's a bunch of unmerged pull requests on the challenges GitHub that have been there a while.

zealous widget
#

here's encryption with reversible automata:

import cellpylib as cpl
import numpy as np

def text_to_bits(text, encoding='ascii', errors='surrogatepass'):
    bits = bin(int.from_bytes(text.encode(encoding, errors), 'big'))[2:]
    return bits.zfill(8 * ((len(bits) + 7) // 8))

def text_from_bits(bits, encoding='ascii', errors='surrogatepass'):
    n = int(bits, 2)
    return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0'

my_string = 'hi there'
print('initial string is: ', my_string)
my_string_binary_array = np.array(list(text_to_bits(my_string)), dtype=int)

cellular_automaton = my_string_binary_array # String is initial state
r = cpl.ReversibleRule(cellular_automaton, 90)
cellular_automaton = cpl.evolve(cellular_automaton[None,:], timesteps=100, apply_rule=r.apply_rule)

print('encoded string: ', ''.join(cellular_automaton[-1].astype(str)))

r._previous_state = cellular_automaton[-1] # Rewind automata by setting last state to previous state
backwards = cpl.evolve(cellular_automaton[-2][None,:], timesteps=100, apply_rule=r.apply_rule)

print('decoded string: ', text_from_bits(''.join(backwards[-1].astype(str)))) # Sanity Check
brazen geyser
#

a key based jumbler using only stdlib (hashlib, base64 and random)

#

can be used to jumble any type of sequence

#
if __name__ == '__main__':
    password = input('enter password:').encode()
    result = jumble_b64(b'hello there', password)
    print(result)
    print(unjumble_b64(result, password))

# enter password:lol
# b'V8dsG=amGgblchUG'
# b'hello there'
gilded orchid
pure dew
#

wow

hollow patrol
#
lambda:(globals().update(__import__('lambdatools').__dict__),gcd:=function('*args',lambda v:(when(lambda v:len(v.args)==2,lambda v:(v.set(a=v.args[0],b=v.args[1]),when(lambda v:v.b==0,lambda v:(result(v.a))),result(v.__ref__(v.b,v.a%v.b)))),otherwise(lambda v:len(v.args)>2,lambda v:(v.set(newGCD=None),foreach('item',v.args,lambda v:(when(lambda v:v.newGCD==None,lambda v:(v.set(newGCD=v.item))),otherwise(lambda v:(v.set(newGCD=gcd(v.newGCD,v.item)))))))),result(v.newGCD))))```
#

That is a 1-lined gcd function using lambdatools

#
lambda: (
    globals().update(__import__('lambdatools').__dict__),
    gcd := function('*args', lambda v: (
      when(lambda v: len(v.args) == 2, lambda v: (
        v.set(a = v.args[0], b = v.args[1]),
        when(lambda v: v.b == 0, lambda v: (
          result(v.a)
        )),
        result(v.__ref__(v.b, v.a % v.b))
      )),
      otherwise(lambda v: len(v.args) > 2, lambda v: (
        v.set(newGCD = None),
        foreach('item', v.args, lambda v: (
          when(lambda v: v.newGCD == None, lambda v: (
            v.set(newGCD = v.item)
          )), otherwise(lambda v: (
            v.set(newGCD = gcd(v.newGCD, v.item))
          ))
        ))
      )),
      result(v.newGCD)
    ))
)```
sick hound
#
(lambda f:f(f))(lambda f:lambda a,b:f(f)(b,a%b)if b else a)```
#

That is a 1-lined gcd function that doesn't use lambdatools

grave rover
#
  8           0 LOAD_CONST               2 (7)
              2 STORE_FAST               2 (mixin_remapped_p_44bef18e7a234b7e)
              4 LOAD_GLOBAL              0 (print)
              6 LOAD_CONST               3 ('p:')
              8 LOAD_FAST                2 (mixin_remapped_p_44bef18e7a234b7e)

  9          10 CALL_FUNCTION            2
``` output: `p: <built-in function print>`
how do I keep doing this shit
#

I should probably just refactor everything shouldnt I

#

because I also need to make function parameters immutable

brazen geyser
#

what be this @grave rover

grave rover
#

pymixin

brazen geyser
#

whats going on in that snippet

grave rover
#

well

#

it stores 7 in the mixin_remapped_p variable

#

but somehow according to the debugger print is stored there

brazen geyser
#

but how

#

what did you do

#

WHAT DID YOU DO

grave rover
#

I wish I knew

grave rover
#

if I change p to anything else it somehow changes to print p: twice

distant wave
#

oh no

grave rover
#

as in stack_top

#

using only bytecode manipulation somehow

#

lemme zip this code

night quarryBOT
#

Hey @grave rover!

It looks like you tried to attach a file type that we do not allow. We currently allow the following file types: .3gp, .3g2, .avi, .bmp, .gif, .h264, .jpg, .jpeg, .m4v, .mkv, .mov, .mp4, .mpeg, .mpg, .png, .tiff, .wmv, .svg, .psd, .ai, .aep, .xcf, .mp3, .wav, .ogg.

Feel free to ask in #community-meta if you think this is a mistake.

grave rover
#

:(

distant wave
#

disabling the referrer header breaks the strangest things

brazen geyser
#

@grave rover

p: p: 7
grave rover
#

yes

#

that's what happens when you change p to anything else

distant wave
#

off topic, here's a fun one

#

!e ```py
def a():
try:
return True
except:
raise
finally:
return False

print(a())

night quarryBOT
#

@distant wave :white_check_mark: Your eval job has completed with return code 0.

False
marsh void
#

!e
def f():
try:
return True
finally:
return False
print(f())

night quarryBOT
#

@marsh void :white_check_mark: Your eval job has completed with return code 0.

False
marsh void
#

@distant wave I mean, that is expected isn’t it

distant wave
#

On one hand, yeah, the behavior is logical

#

On the other hand, it can really make intersting and unexpected bugs

marsh void
#

yeah

#

return in finally silences all errors

sick hound
grave rover
#

try-finally works like this:

try:
    return 1
finally:
    return 2
``` ```
SETUP_FINALLY
LOAD_CONST 1
CALL_FINALLY
RETURN_VALUE

POP_TOP
LOAD_CONST 2
RETURN_VALUE
END_FINALLY
zealous widget
#

that's weird

pure dew
#

mart are you ok

marsh void
#

yeah

worthy briar
#

Can anyone help me understand why python's logging module creates a StreamHandler on import, but only on some distributions? weird.. (note: happens on any python3)
On Mac

Python 3.5.6 (default, Dec 19 2019, 14:59:39) 
[GCC 4.2.1 Compatible Apple LLVM 11.0.0 (clang-1100.0.33.8)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import logging
>>> logging.getLogger().handlers
[<logging.StreamHandler object at 0x108fc2630>]

Linux:

Python 3.7.4 (default, Jan  3 2020, 19:27:19)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import logging
>>> logging.getLogger().handlers
[]
>>> 

I can't seem to find any explanation about this.

distant wave
#

The streamhandler is initialized whenever logging's default configuration is initialized, which happens if it's called directly or something attempts to log something at any loglevel

#

It's possible something run during repl startup is sending a debug log message, which then initializes the handler

#

It could be caused by a hashlib import, with the warning message caused by an OSX-specific openssl support difference occurring and being silenced behind the scenes.

worthy briar
#

hmm that's a good idea, thanks!

hollow patrol
#

@sick hound Your function doesn't work with *args.

#

But it still works, so, I guess that's pretty cool

calm rampart
#

lmao ```py

numpy.array(["a", "b", "c"], dtype=object).dot([1, 2, 3])
'abbccc'```

glacial rampart
#

@thin trout I'm very late but you can raise in lambdas: (0for[]in[]).throw(ImportError('nope!'))

sick hound
#

for key, value in self.settings["credentials"].items():
self._setattr_(key, value)

#

I dare someone to turn this into a one liner

wind maple
#

self.__dict__.update(self.settings['credentials'])

sick hound
#

doesn't wortk

#

Nvm that

#

but i don't think it will

wind maple
#

why do you think that

sick hound
#

oh it does

wind maple
#

why would it not

sick hound
#

well

#

I had never thought of that

wind maple
#

🤨

sick hound
#

Lol

proper vault
#

any(setattr(self, k, v) for k,v in self.settings['credentials'].items())

#

every for loop with its body in one line is trivial to turn into a oneliner

sick hound
#

Hmm

sick hound
#

Is this esoteric

#

lambda n: reduce( (lambda r,x: r-set(range(x**2,n,x)) if (x in r) else r), range(2,int(n**0.5)), set(range(2,n)))

night quarryBOT
#

:incoming_envelope: :ok_hand: applied mute to @sick hound until 2020-01-06 05:24 (9 minutes and 59 seconds) (reason: duplicates rule: sent 4 duplicated messages in 10s).

pure dew
#

wew

snow beacon
#

I have to ask what it does, so it's esoteric. Does it find primes?

marsh void
#

!e
from functools import *; f = lambda n: reduce( (lambda r,x: r-set(range(x**2,n,x)) if (x in r) else r), range(2,int(n**0.5)), set(range(2,n))); print(f(100))

night quarryBOT
#

@marsh void :white_check_mark: Your eval job has completed with return code 0.

{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}
thin trout
#

Looks like prime numbers

marsh void
#

yeah

#

!e from functools import *; f = lambda n: reduce((lambda r,x: r-set(range(x**2,n,x)) if (x in r) else r), range(2,int(n**0.5)), set(range(2,n))); p=lambda n:[x for x in range(2,n+1)if all(x%y for y in range(2,int(x**.5)+1))]; from timeit import timeit; t = lambda s: timeit(s, globals=globals(), number=1000); print(t('f(100)')); print(t('p(100)'))

night quarryBOT
#

@marsh void :white_check_mark: Your eval job has completed with return code 0.

001 | 0.018206743523478508
002 | 0.14901408832520247
marsh void
#

woah it’s fast

#

second is my p function

thin trout
#

Let me.. just..

#
from functools import *

f = lambda n: reduce((lambda r,x: r-set(range(x**2,n,x)) if (x in r) else r), range(2,int(n**0.5)), set(range(2,n)))

p=lambda n:[x for x in range(2,n+1)if all(x%y for y in range(2,int(x**.5)+1))]

from timeit import timeit
t = lambda s: timeit(s, globals=globals(), number=1000)
print(t('f(100)'))
print(t('p(100)'))```
#

okay now I can read it 😛

#

Well, more or less

distant wave
#

!e ```py
from collections import defaultdict
configuration = defaultdict(dict)
configuration["test"] = [["test-2", "test", "test-3"], ["test"]]

for instance_set in configuration.values():
for instance in instance_set:
for element in instance:
if not element in configuration[element]:
print(1)

night quarryBOT
#

@distant wave :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 5, in <module>
003 | RuntimeError: dictionary changed size during iteration
004 | 1
005 | 1
006 | 1
007 | 1
sick hound
#

F

formal sandal
#

Collatz conjecture in stekk! The run function will return the Collatz chain for a given N.

even := { (.dup 2 ./i 2 .* .=) };

next := {
    if (.dup .even) 
        (2 ./i)
    else
        (3 .* 1 .+)
};

run := {
    if (.dup 1 .=)
        [()]
    else
        ([(.dup)] .swap .next .run .++)
};
#

If anyone hasn't heard of it, the conjecture is that if

f(even k) = k/2
f(odd k) = 3k+1

Then for any natural number N it is true that if you apply the f to N, then to its result and so on, you will inevitably end up at 1.

tropic night
#

so could anyone please explain to me in English what's going on here

#

!e

for [] in [()]*2:
    print(42)
night quarryBOT
#

@tropic night :white_check_mark: Your eval job has completed with return code 0.

001 | 42
002 | 42
tropic night
#

found this image online.. its from a few days ago

whole kiln
#

[()]*2 just creates a list with 2 empty tuples

#

I've not seen for [] in ... though

tropic night
#

yeah.. i get the tuple.. but what is it doing

#

is it unpacking empty tuples in a list?

edgy kelp
#

unpacked into nothing

tropic night
#

like.. i can run it and see why its working, but why is it working...

whole kiln
#

!e ```py
[] = [()]*2

night quarryBOT
#

@whole kiln :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 1, in <module>
003 | ValueError: too many values to unpack (expected 0)
tropic night
#

like just change the sequence to something else..

#

and whats going on with the element part...

#

does it need something that is falsy like empty elements to work?

#

since you are asking it to unpack 0 values

#

and why does it expect 0 values in the first place

#

for () ... -> works

#

for '' ... -> does not

#

when i think i have figured it out, i realize i do not

whole kiln
#

My example was wrong

proper vault
whole kiln
#

cause it tries to unpack a single element

#

rather than the whole thing

proper vault
#

it is unpacking

edgy kelp
#

you give it an empty sequence to unpack for every iteration

#

then it's just the unpacking syntax

proper vault
#

!e

[] = ()
night quarryBOT
#

@proper vault :warning: Your eval job has completed with return code 0.

[No output]
proper vault
#

this is essentially what it does

#

twice, once for each ()

tropic night
#

so its just unpacking and the [] is just to make it syntactical confusing?

proper vault
#

well, the [] is essentially unpack 0 elements.

#
it = iter([()]*2)
while True:
  try:
    [] = next(it)  # [] = ()
  except StopIteration:
    break
  else:
    print(42)
#

roughly equivalent

tropic night
#

oh i get it 😄

#

thanks @proper vault

#

that was very clear

proper vault
#

np

proper vault
#
(lambda kivy_:kivy_.lang.Builder.load_string('<Widget>:\n\tcanvas:\n\t\tTriangle:\n\t\t\tpoints:0,0,self.width/2,self.top,self.right,0')or type("MainApp",(kivy_.app.App,),{"build":lambda s:kivy_.uix.widget.Widget()})().run())(__import__('kivy', fromlist=['lang','app','uix']))

any easier way to do this

rugged sparrow
#

@sick hound wdym

brazen geyser
#
import ctypes as ct


class StructureMeta(type(ct.Structure)):
    def __new__(mcs, name, bases, namespace):
        cls = super().__new__(mcs, name, bases, namespace)

        fields = dict()
        for base in reversed(cls.mro()):
            try:
                fields.update(base.__annotations__)
            except AttributeError:
                pass

        cls._fields_ = list(fields.items())
        return cls


class Structure(ct.Structure, metaclass=StructureMeta):
    pass

an alternative ctypes.Structure that uses type annotations to populate its fields, so you get proper autocompletion. also it will inherit fields from its parents.

#

e.g.

class ExampleStruct(Structure):
    member_1: ct.c_int
    member_2: ct.c_char
marsh void
#

cool!

brisk zenith
#

i implemented that a long time ago in my cpystructs code and then used it to make the various object structs used in cpython. i should get back to trying that.

#

although your implementation looks simpler (and therefore better) than mine. mind if i steal borrow it at some point? :D

gilded orchid
#

permenent borrowing

snow beacon
#

Theft, liberation, what's the difference? A rose by any other name would smell as justified.

brazen geyser
#

lol nice

#

yea sure go for it

#

how did you implement yours? is there a repo?

brisk zenith
#

uh yeah somewhere i think

#

oh actually, my initial implementation of cpystructs on github doesn't use that idea. although i know i've implemented it before

#
class TypedStructure(ctypes.Structure):
    def __new__(cls, *args, **kwargs):
        cls.ensure_fields()
        return super().__new__(cls, *args, **kwargs)

    def __init__(self, *args, **kwargs):
        print(self._fields_)

    @classmethod
    def ensure_fields(cls):
        if not hasattr(cls, "_fields_"):
            fields = typing.get_type_hints(cls)
            cls._fields_ = list(fields.items())

i don't think it handled inheritence either. might be nice to see if i can use yours to simplify stuff

brazen geyser
#

oh cool didnt know about get_type_hints

#

so it does the reverse mro walk too, nice

brisk zenith
#

oh does it?

#

it would make sense actually

brazen geyser
#
typing.get_type_hints(obj[, globals[, locals]])¶
Return a dictionary containing type hints for a function, method, module or class object.

This is often the same as obj.__annotations__. In addition, forward references encoded as string literals are handled by evaluating them in globals and locals namespaces. If necessary, Optional[t] is added for function and method annotations if a default value equal to None is set. For a class C, return a dictionary constructed by merging all the __annotations__ along C.__mro__ in reverse order.
brisk zenith
#

oh huh

#

nice.

brazen geyser
#

v2 :p

class StructureMeta(type(ctypes.Structure)):
    def __new__(mcs, name, bases, namespace):
        cls = super().__new__(mcs, name, bases, namespace)

        cls._fields_ = list(
            typing.get_type_hints(cls).items()
        )

        return cls
brisk zenith
#

the best type of code stealing is when you learn from each other :D

brazen geyser
#

🤝

brisk zenith
#

@brazen geyser oh i remember why i didn't create the fields directly in the __new__. that doesn't allow for forward-referencing typehints

brazen geyser
#

hmm

brisk zenith
#

that's why i made it initialise the fields once an instance was being created.

#

but i'm not sure if there's a better alternative.

brazen geyser
#

im thinking of one rn

gilded orchid
#

what does __new__ do?

brazen geyser
#

working out a way to come back later and fill in the field type

#

if name is not found yet at time of creation

brisk zenith
#

oh interesting.

#

the issue with that is that _fields_ cannot be modified properly after it's first created

#

because you can't just insert spaces into C structs when you want new things in there during runtime

brazen geyser
#

right, so setting _fields_ would be deferred altogether until all field types are corrctly resolved

#

or correctly resolvable

brisk zenith
#

@gilded orchid take a look at this. it's nothing esoteric really: https://howto.lintel.in/python-__new__-magic-method-explained/

#

@brazen geyser i figured that the very latest point at which that could be possible is just before struct initialisation

#

because it clearly can't be any later - that's when _fields_ is set in stone.

#

and any earlier risks evaluating it too early.

#

i.e, when the typehints being forward-referenced are not yet existent.

#

i can't believe i had the mental capacity to figure this out back then, i don't know what's happened since haha :D

brazen geyser
#

originally i'd just settled for writing off forward references as a tradeoff

#

but now that you brought it up again some lightbulbs went off in my head

#

so i know that from __futre__ import annotations somehow defers annotation resolution until the end of compilation

#

perhaps there is a way to hook into this

#

aside from that was thinking about altering the bytecode of the module frame to add a callback at the end

#

but that's gonna be a headache and a half probably

brisk zenith
#

definitely sounds like it.

#

fiddling with __future__ on its own is a no-go because it ties so closely to the interpreter and is very likely to be unstable

brazen geyser
#

it's a reasonable tradeoff imo

#

:p

#

not that im giving up

#

... yet

sick hound
#

@brazen geyser yea annotations use an internal ast unparser which can parse simple expressions

#

there is literally a big c function that compares import string with known future tags

brazen geyser
#

huh

#

interesting

grave rover
#

Weirdest thing ever rn

pure dew
#

what should it do?

snow beacon
#

Presumably add one, rather than add negative one.

marsh void
#
>>> dis.dis('j+1')
  1           0 LOAD_NAME                0 (j)
              2 LOAD_CONST               0 (1)
              4 BINARY_ADD
              6 RETURN_VALUE``` hm?
brazen geyser
#

how to make this work?

>>> def test():
    __module__ = '__main__'
    __qualname__ = 'test'

    def __init__(self):
        self.x = 12
    
    def crap(self):
        print(self)

        
>>> cls = __build_class__(test, 'test')
>>> cls().crap()
Traceback (most recent call last):
  File "<pyshell#107>", line 1, in <module>
    cls().crap()
AttributeError: 'test' object has no attribute 'crap'
>>> 
#
>>> code = """
__module__ = '__main__'
__qualname__ = 'test'

def __init__(self):
    self.x = 12
    
def crap(self):
    print(self)
"""
>>> func = FunctionType(compile(code, '<func>', 'exec'), globals())
>>> cls = __build_class__(func, 'test')
>>> cls().crap()
<__main__.test object at 0x000001FAFFB01048>
>>> 

why does this work but not that

#

looking at the difference in bytecode, the only thing that stands out is the use of STORE_NAME rather than STORE_FAST

#

and func's co_flags are set to 64, whereas test's are set to 67

grave rover
#

what's a good way to print N strings of variable size side by side?

vestal solstice
#

so they have newlines?

#

how many strings in this picture?

#

3?

grave rover
marsh void
#

what’s that lol

brazen geyser
#

ascii cards

#

solitaire maybe

#

?

grave rover
#

the solitaire challenge that's pinned

#

but for some reason I have an infinite card stack :P

marsh void
#

lol

grave rover
#

alright it works ish

#

now to make it a LOT faster

#

I should be able to use threads here but eh

#

dont wanna forkbomb my pc

edgy kelp
#

each pile with its own thread? 😄

formal sandal
#

Are you using ncurses?

grave rover
#

Nope

#

I figured I could just use zip_longest and since they have a constant width I can just use a default value in case of None

grave rover
#

it's been going for 45 mins with a random start phase

#

ohno

#

optimized the code, lets try again

grave rover
#

taking its time, though it already got 2 piles

#

I wonder how much faster it'd be if I didnt print

proper vault
#

I saw that

rugged sparrow
#
[(e:=enumerate),(s:=(exit('Invalid Size')if int(i)<3 else int(i))if(i:=input('Board Size (Min 3): ')).isnumeric()else 0),(b:=[[dict(d=__import__('random').choice([0]*s+[1]*(s//3)),n=0)for()in[()]*s]for()in[()]*s]),[[[[t.update(n=t['n']+b[i+x][j+y]['d'])for y in[-1,0,1]if all(map(lambda v:v>=0and v<len(r),[i+x,j+y]))]for x in[-1,0,1]]for j,t in e(r)]for i,r in e(b)],b[0][0].update(d=b[0][0]['d']|8),[*iter(lambda h='\x1b[':all(all((t['d']&1and t['d']&2)or t['d']&4for t in r)for r in b)or[(p:=print)(h+'2J'),[p('',*[h+f'{"7"if t["d"]&8else"0"}m{t["n"]if t["d"]&4else"F"if t["d"]&2else"#"}{h}0m'for t in r])for r in b],p(f'\n{h}7mMove (wasd), Flag (f) or Clear (c):{h}0m '),[*[(lambda t,c,n:lambda:[t.update(d=t['d']^8),b[p][q].update(d=b[p][q]['d']|8)]if(p:=c[0]+n[0])>=0and p<len(b[0])and(q:=c[1]+n[1])>=0and q<len(b[0])else 0)(*(g:=lambda b:sorted([[(t,(i,j))for j,t in e(r)if t['d']&8]for i,r in e(b)])[-1][0])(b),n)for n in zip([-1,0,1,0],[0,-1,0,1])],*map(lambda o:lambda:(t:=g(b)[0]).update(d=exit('You Lose')if t['d']&1and o==4else t['d']^o),[2,4]),p]['wasdfc'.find(__import__('sys').stdin.read(1))]()][0],1)],exit('You win')]```
#

@proper vault it had a bug

proper vault
#

I know

rugged sparrow
#

fixed it now tho

#

i think

proper vault
rugged sparrow
#

what version?

proper vault
#

the one you just posted

rugged sparrow
#

i meant of python

proper vault
#

3.8.0

rugged sparrow
#

tf?

#
Python 3.8.0 (v3.8.0:fa919fdf25, Oct 14 2019, 10:23:27) 
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> [(e:=enumerate),(s:=(exit('Invalid Size')if int(i)<3 else int(i))if(i:=input('Board Size (Min 3): ')).isnumeric()else 0),(b:=[[dict(d=__import__('random').choice([0]*s+[1]*(s//3)),n=0)for()in[()]*s]for()in[()]*s]),[[[[t.update(n=t['n']+b[i+x][j+y]['d'])for y in[-1,0,1]if all(map(lambda v:v>=0and v<len(r),[i+x,j+y]))]for x in[-1,0,1]]for j,t in e(r)]for i,r in e(b)],b[0][0].update(d=b[0][0]['d']|8),[*iter(lambda h='\x1b[':all(all((t['d']&1and t['d']&2)or t['d']&4for t in r)for r in b)or[(p:=print)(h+'2J'),[p('',*[h+f'{"7"if t["d"]&8else"0"}m{t["n"]if t["d"]&4else"F"if t["d"]&2else"#"}{h}0m'for t in r])for r in b],p(f'\n{h}7mMove (wasd), Flag (f) or Clear (c):{h}0m '),[*[(lambda t,c,n:lambda:[t.update(d=t['d']^8),b[p][q].update(d=b[p][q]['d']|8)]if(p:=c[0]+n[0])>=0and p<len(b[0])and(q:=c[1]+n[1])>=0and q<len(b[0])else 0)(*(g:=lambda b:sorted([[(t,(i,j))for j,t in e(r)if t['d']&8]for i,r in e(b)])[-1][0])(b),n)for n in zip([-1,0,1,0],[0,-1,0,1])],*map(lambda o:lambda:(t:=g(b)[0]).update(d=exit('You Lose')if t['d']&1and o==4else t['d']^o),[2,4]),p]['wasdfc'.find(__import__('sys').stdin.read(1))]()][0],1)],exit('You win')]
Board Size (Min 3): 

proper vault
#

it happens once you enter a number

rugged sparrow
#

 # # #
 # # #
 # # #

Move (wasd), Flag (f) or Clear (c): 
``` this happens when you enter a number
#

(3 here obv)

#

can you type '0'.isnumeric into your interpreter?

#

@proper vault ^

proper vault
#

apparently a repl problem

#

gonna blame windows, works fine in pycharm

rugged sparrow
#

prob a windows problem

#

i tested on macos and linux

brazen geyser
#

no errors but

proper vault
#

ye, windowses fault

brazen geyser
#

did you try it in command prompt

rugged sparrow
#

yea i use some terminal codes

brazen geyser
#

happens in command prompt too

#

iirc you need to use something like colorama to make ansi escape codes work in windows terminal

rugged sparrow
#

yea i'd need to add __import__('colorama').init() to the beginning of the list comp

proper vault
#

pycharm terminal does work

rugged sparrow
#

¯_(ツ)_/¯

#

windows man

brazen geyser
#

pycharm does some magic to terminal stdout

rugged sparrow
#

i think it also uses colorama

brazen geyser
#

it screws up piping in some instances iirc

rugged sparrow
#

i do think that bool error was bizarre tho

proper vault
#

oh wait, I know

#

I was messing with builtins in that instance and replaced print

#

lmao

rugged sparrow
#

that would do it

#

lmao

#

but yea its full minesweeper in one listcomp

#

still working on adding the recursive clearing that normal minesweeper has

marsh void
#

does colorama monkey patch print or something?

grave rover
#

yes

brazen geyser
#

hijacks stdout altogether iirc

#
ANSI escape character sequences have long been used to produce colored terminal text and cursor positioning on Unix and Macs. Colorama makes this work on Windows, too, by wrapping stdout, stripping ANSI sequences it finds (which would appear as gobbledygook in the output), and converting them into the appropriate win32 calls to modify the state of the terminal. On other platforms, Colorama does nothing.
marsh void
#

yeah

#

@brazen geyser so, windows console only has certain colors?

brazen geyser
#

no idea

marsh void
#

aight

wind maple
#

no

#

On windows you need to enable ANSI escapes through the windows API

#

But it supports 24-bit colour

#

I haven't tried if it supports all the useful features though

grave rover
#

reworked the entire code for solving the boards in a faster language (kotlin/native) and gave it a maximum move depth of 200

Let's see what it comes up with

grave rover
#

now to do this in python again

zealous widget
#

now i want to do this terminal game to add to my collection

grave rover
#

it's part of molek-syntez which I definitely recommend as its a great logical thinking puzzle game

#

alternatively I could rewrite this into an engine to play the game

zealous widget
#

looks like freecell

#

kind of

grave rover
#

see pins

zealous widget
#

40 chars? that's not a lot of chars

grave rover
#

idk what I meant with that tbh

#

:P

zealous widget
#

so is it like freecell

grave rover
#

idk freecell

zealous widget
#

you can move descending stacks --- but the stacks also need to be black,red,black,red alternating

grave rover
#

isnt that just solitaire?

zealous widget
#

no, but it's similar

#

that is, all the cards are already dealt out in freecell

grave rover
#

I see

grave rover
#

whoops wait

#

main class typo

rugged sparrow
#
[(e:=enumerate),(s:=(exit('Invalid Size')if(int(i)if(i:=input('Board Size (Min 3): ')).isnumeric()else 0)<3else int(i))),(b:=[[dict(d=__import__('random').choice([0]*s+[1]*(s//3)),n=0)for()in[()]*s]for()in[()]*s]),[[[t.update(n=t['n']+b[i+x][j+y]['d'])for y in[-1,0,1]for x in[-1,0,1]if all(map(lambda v:v>=0and v<len(r),[i+x,j+y]))]for j,t in e(r)]for i,r in e(b)],(f:=lambda x,y,v:(t:=b[x][y]).update(d=t['d']^v))(0,0,8),[*iter(lambda h='\x1b[':all(all((t['d']&1and t['d']&2)or t['d']&4for t in r)for r in b)or[(p:=print)(h+'2J'),[p('',*[h+f'{"7"if t["d"]&8else"0"}m{t["n"]if t["d"]&4else"F"if t["d"]&2else"#"}{h}0m'for t in r])for r in b],p(f'\n{h}7mMove (wasd), Flag (f) or Clear (c):{h}0m '),[*[(lambda t,c,n:lambda:[f(*c,8),f(p,q,8)]if(p:=c[0]+n[0])>=0and p<len(b[0])and(q:=c[1]+n[1])>=0and q<len(b[0])else 0)(*(g:=lambda b:sorted([[(t,(i,j))for j,t in e(r)if t['d']&8]for i,r in e(b)])[-1][0])(b),n)for n in zip([-1,0,1,0],[0,-1,0,1])],lambda:f(*g(b)[1],2),lambda:exit('You Lose')if(t:=g(b))[0]['d']&1else f(*t[1],4)if t[0]['n']else(r:=lambda i,j,l:[[[f(*c,4),r(*c,l+[c])if t['n']==0and c not in l else 0]if not(t:=b[i+x][j+y])['d']&4and not t['d']&1else 0]for y in[0,1,-1]for x in[0,1,-1]if all(map(lambda v:v>=0 and v<len(b[0]),(c:=(i+x,j+y))))])(*t[1],[]),p]['wasdfc'.find(__import__('sys').stdin.read(1))]()][0],1)],exit('You win')]
#

i added the recursive clearing

grave rover
#

Board<C : Card<C, S>, S : Stack<C, S>> surely there's a better way to do this

snow beacon
#

What does that notation represent?

grave rover
#

it'd be like uhh

#

Board[C:=Card[C, S], S:=Stack[C, S]] where C and S are defined recursively

night quarryBOT
#

Hey @grave rover!

It looks like you tried to attach a file type that we do not allow. We currently allow the following file types: .3gp, .3g2, .avi, .bmp, .gif, .h264, .jpg, .jpeg, .m4v, .mkv, .mov, .mp4, .mpeg, .mpg, .png, .tiff, .wmv, .svg, .psd, .ai, .aep, .xcf, .mp3, .wav, .ogg.

Feel free to ask in #community-meta if you think this is a mistake.

grave rover
#

oh right

grave rover
wind maple
#

This is a python server pithink

grave rover
#

yes

#

but I did solve the problem in python

#

it's just that I rewrote it in Kotlin to actually see any results :^)

#

then he wanted to play it so I reworked it to allow him to play

next mist
#

@rugged sparrow that is disgusting

#

and i was proud of mine mess baby until i saw that

#
class BoopBoop():
    
    def BorpBif(BepaBip, BupBup):
        BapBif = BepaBip
        Bip = ""
        BopBip = Bip.join(BapBif)
        BepBid = "urgle"
        BufBip = (BopBip+" "+BupBup+BepBid)
        print(BufBip)
    def Bobbup(Blup):
        BupBup = Blup
        BefBip = {
            "BabBab":"a", "BadBab":"b", "BabBap":"c", "BabBad":"d",
            "BebBeb":"e", "BedBeb":"f", "BedBep":"g", "BebBed":"h", 
            "BibBib":"i", "BidBib":"j", "BidBip":"k", "BibBid":"l",
            "BobBob":"m", "BodBob":"n", "BodBop":"o", "BobBod":"p",
            "BubBub":"q", "BudBub":"r", "BudBup":"s", "BubBud":"t",
            "BaabBaab":"u", "BaadBaab":"v", "BaadBaap":"w", "BaabBaad":"x",
            "BoobBoob":"y", "BoodBoob":"z", "BoobBoop":" "
        }
        BepaBip = (BefBip["BoobBoob"],BefBip["BodBop"],BefBip["BaabBaab"],BefBip["BudBub"],BefBip["BoobBoop"],
            BefBip["BodBob"],BefBip["BabBab"],BefBip["BobBob"],BefBip["BebBeb"],BefBip["BoobBoop"],BefBip["BibBib"],BefBip["BudBup"])
        BoopBoop.BorpBif(BepaBip, BupBup)
    def BipBop(BaapBip, Bup):
        BupBeep = (BaapBip*Bup)
        BepBep = (''.join(sorted(BupBeep)))
        Blup = (BepBep[len("ba")]+BepBep[len("Boof")])
        BoopBoop.Bobbup(Blup)

    def BopBid():
        Bup = len("Bap")
        BoopBip = "BabBoop>>>"
        BaapBip = input(BoopBip)
        BoopBoop.BipBop(BaapBip, Bup)
if __name__ == '__main__':
    BoopBoop.BopBid()```
rugged sparrow
#

mine is beautiful code cereal as my friend called it

next mist
#

does it need anything to run? didnt work for me

rugged sparrow
#

what error?

next mist
#
[(e:=enumerate),(s:=(exit('Invalid Size')if(int(i)if(i:=input('Board Size (Min 3): ')).isnumeric()else 0)<3else int(i))),(b:=[[dict(d=__import__('random').choice([0]*s+[1]*(s//3)),n=0)for()in[()]*s]for()in[()]*s]),[[[t.update(n=t['n']+b[i+x][j+y]['d'])for y in[-1,0,1]for x in[-1,0,1]if all(map(lambda v:v>=0and v<len(r),[i+x,j+y]))]for j,t in e(r)]for i,r in e(b)],(f:=lambda x,y,v:(t:=b[x][y]).update(d=t['d']^v))(0,0,8),[*iter(lambda h='\x1b[':all(all((t['d']&1and t['d']&2)or t['d']&4for t in r)for r in b)or[(p:=print)(h+'2J'),[p('',*[h+f'{"7"if t["d"]&8else"0"}m{t["n"]if t["d"]&4else"F"if t["d"]&2else"#"}{h}0m'for t in r])for r in b],p(f'\n{h}7mMove (wasd), Flag (f) or Clear (c):{h}0m '),[*[(lambda t,c,n:lambda:[f(*c,8),f(p,q,8)]if(p:=c[0]+n[0])>=0and p<len(b[0])and(q:=c[1]+n[1])>=0and q<len(b[0])else 0)(*(g:=lambda b:sorted([[(t,(i,j))for j,t in e(r)if t['d']&8]for i,r in e(b)])[-1][0])(b),n)for n in zip([-1,0,1,0],[0,-1,0,1])],lambda:f(*g(b)[1],2),lambda:exit('You Lose')if(t:=g(b))[0]['d']&1else f(*t[1],4)if t[0]['n']else(r:=lambda i,j,l:[[[f(*c,4),r(*c,l+[c])if t['n']==0and c not in l else 0]if not(t:=b[i+x][j+y])['d']&4and not t['d']&1else 0]for y in[0,1,-1]for x in[0,1,-1]if all(map(lambda v:v>=0 and v<len(b[0]),(c:=(i+x,j+y))))])(*t[1],[]),p]['wasdfc'.find(__import__('sys').stdin.read(1))]()][0],1)],exit('You win')]
       ^
SyntaxError: invalid syntax```
rugged sparrow
#

3.8

#

it needs 3.8

next mist
#

ah ok

#

thats why

#

im on 3.6.6

rugged sparrow
#

i used walrus's to shorten it

#

ah

#

yea that would do it

marsh void
#

do w/out walrus

rugged sparrow
#

I could, but if it’s a part of official python, why not

marsh void
#

many people are 3.7 @rugged sparrow

rugged sparrow
#

That's fair

next mist
#

im only 3.6.6 😦

rugged sparrow
#

I'll rewrite Tonight to use a dictionary

proper vault
#

why not use

a = 1;a + a #into
(lambda a: a + a)(1)
pure dew
#

semicolons is cheating

proper vault
#

you only use the second line

rugged sparrow
#

@proper vault I actually think imma do a different method

rugged sparrow
#
[[[[[t.update(n=t['n']+b[i+x][j+y]['d'])for y in[-1,0,1]for x in[-1,0,1]if all(map(lambda v:v>=0and v<len(r),[i+x,j+y]))]for j,t in e(r)]for i,r in e(b)],f(b,0,0,8),[*iter(lambda h='\x1b[':all(all((t['d']&1and t['d']&2)or t['d']&4for t in r)for r in b)or[p(h+'2J'),[p('',*[h+f'{7if t["d"]&8else 0}m{t["n"]if t["d"]&4else"F"if t["d"]&2else"#"}{h}0m'for t in r])for r in b],p(f'\n{h}7mMove (wasd), Flag (f) or Clear (c):{h}0m '),[*[(lambda t,c,n:lambda:[f(b,*c,8),f(b,c[0]+n[0],c[1]+n[1],8)]if c[0]+n[0]>=0and c[0]+n[0]<len(b[0])and c[1]+n[1]>=0and c[1]+n[1]<len(b[0])else 0)(*g(b,e),n)for n in zip([-1,0,1,0],[0,-1,0,1])],lambda:f(b,*g(b,e)[1],2),lambda:exit('You Lose')if g(b,e)[0]['d']&1else f(b,*g(b,e)[1],4)if g(b,e)[0]['n']else r(b,f,r,*g(b,e)[1],[]),p]['wasdfc'.find(__import__('sys').stdin.read(1))]()][0],1)],exit('You win')]for e,p,b,f,g,r in[(enumerate,print,(lambda s:[[dict(d=__import__('random').choice([0]*s+[1]*(s//3)),n=0)for()in[()]*s]for()in[()]*s])((lambda i:int(i)if i.isnumeric()and int(i)>2else(exit('Invalid Size')))(input('Board Size (Min 3): '))),lambda b,x,y,v:b[x][y].update(d=b[x][y]['d']^v),lambda b,e:sorted([[(t,(i,j))for j,t in e(r)if t['d']&8]for i,r in e(b)])[-1][0],lambda b,f,r,i,j,l:[[[f(b,i+x,j+y,4),r(b,f,r,i+x,j+y,l+[(i+x,j+y)])if b[i+x][j+y]['n']==0and(i+x,j+y)not in l else 0]if not b[i+x][j+y]['d']&4and not b[i+x][j+y]['d']&1else 0]for y in[0,1,-1]for x in[0,1,-1]if all(map(lambda v:v>=0and v<len(b[0]),(i+x,j+y)))])]]
``` @proper vault @next mist @marsh void here is one with no walrus's
marsh void
#

bless you, haha

rugged sparrow
#

i used a single loop for loop to make my local vars

#

instead of walrus's

#

which means this function now does nothing to the global scope

next mist
#

Thanks I hate it

rugged sparrow
#

youre welcome

abstract moth
#

I am getting some anxiety from just looking at that

pure dew
#

your exit calls aren't esoteric enough

#

have it raise an exception instead

brisk zenith
#

(0for()in()).throw(Exception("heck"))

pure dew
#

precisely

rugged sparrow
#

Lmao

snow beacon
#

It's nicer on the player if they're running from a repl if it's an exception and not a call to exit.

rugged sparrow
#

True. I'll change that on Monday

#

Might just make the list comp exit properly

thin trout
#

I guess it doesn't really matters here, but it is cool to know, not putting a space between keywords (0for()in() instead of 0 for () in ()) works in all major python implementations, except micropython, which is kind of fun

#

So, if you are doing esoteric for micropython, you need spaces everywhere :D

marsh void
#

sad

grave rover
#

Such a flawed implementation smh

snow beacon
#

It does what it sets out to do.

pure dew
#

why does micropython require spaces

#

does it use a lexer like my js expression parser?

#

const lex = c => c.split(" ").map(s => s.trim()).filter(s => s.length) this requires spaces around every token lmao

sick hound
#

print ( "hello world" )

pure dew
#

yes except that wouldn't be valid for my thing

vestal solstice
#

space inside a token?

thin trout
#

Spaces around a token are required

pure dew
#

well i mean my parser requires this sin ( max ( 2 3 x ) / 3 ) * PI

thin trout
#

No, only between letters and numbers

wind maple
#

you're talking about two separate things

#

lol

pure dew
#

yes

#

@thin trout I'm saying my custom parser requires spaces like that and was asking if MicroPython was the same

#

μPython doesnt have unicode name escapes?

thin trout
#

Nope

sick hound
#

I've finally completed visualization of token matching through BRM

pure dew
#

bruh

#

thats cool

#

yo this is cool as fuck coding: brm-utf8

#

gives me so many ideas for absolute shitcode :)

sick hound
#

The reason I wrote this is supporting dead peps, which contains tons of shitcode

#
    interface Foo:
        pass
    print(Foo.__abstractmethods__)


    for i indexing e in some_iterator:
        print(i, e)
#
    for i in 3:
        if i > 1:
            print(i)
#

!pep 245

night quarryBOT
#
**PEP 245 - Python Interface Syntax**
Status

Rejected

Python-Version

2.2

Created

11-Jan-2001

Type

Standards Track

sick hound
#

!pep 212

night quarryBOT
#
**PEP 212 - Loop Counter Iteration**
Status

Rejected

Python-Version

2.1

Created

22-Aug-2000

Type

Standards Track

sick hound
#

etc.

#

I posted the project about implementing these on the chanel if you would like to see actual implementation

pure dew
#

yes please

#

thats cool

#

i could port pyskell to this lmao

marsh void
#

!pep 315

night quarryBOT
#
**PEP 315 - Enhanced While Loop**
Status

Rejected

Python-Version

2.5

Created

25-Apr-2003

Type

Standards Track

marsh void
#

this one seemed pretty interesting actually

thin trout
#

I seems more dumb than interesting to me tbh :D

#

Wasn't this guy Raymond Hettinger, one of the first python dev?

valid stone
#

Anyone know how this program does this?
It sends click requests without moving the mouse at all

#

and if it's possible in Python

brisk zenith
#

it is easily possible, there's a module on PyPI that you can install with pip called pynput (just to name one option) which lets you control the mouse and keyboard using python. it's got nothing to do with #esoteric-python though :D

#

(@valid stone)

#

i'm not sure if it'll be able to do it without moving the mouse as in the thing you sent, but i don't see why it shouldn't (and if pynput doesn't do it, there will likely be similar modules that can)

marsh void
sick hound
#

@marsh void for 315 you can probably do something like that in brm,

    @pattern("name", "colon", "newline", "indent", "(.*?)", "dedent", "name", "(.*?)", "colon", "newline", "indent", "(.*?)", "dedent")
    def indexing_transformer(self, *stream_tokens):
        stream_token = iter(stream_tokens)
        if next(stream_token).string != "do":
            return
        next(stream_token) # colon
        next(stream_token) # newline
        next(stream_token) # indent
        setup, dedent = self.until(token.DEDENT, stream_token)
        statement = next(stream_token)
        if statement.string != "while":
            return
        test, colon = self.until(token.COLON, stream_token)
        newline = next(stream_token)
        indent = next(stream_token)
        body, dedent = self.until(token.DEDENT, stream_token)
        return (*setup, statement, *test, colon, newline, indent, *body, *setup, dedent)
marsh void
#

oh, ok

valid stone
#

@brisk zenith I think the issue is the moving without the mouse part. I already coded something like it in Pyautogui but I don't like the fact it takes control of my mouse.

#

I've used pyninput too and can't seem to find a way to do this either

valid stone
#

@marsh void Maybe I'm doing something wrong but ctypes still moves the mouse when clicking.

proper vault
#

maybe the original position is stored and the mouse is just moved really quickly

valid stone
#

Not too sure but I really doubt it. There's almost no delay or lag in my mouse in the video. When I tried what you said, there were always slight hiccups

gilded orchid
#

from looking around I can't find too much on it

valid stone
#

Yeah I tried that too couldnt get it to work with coorindates. Also had to select a window each time which seems overcomplicated :/

sick hound
#

maybe it's sending messages to the window?

marsh void
#

!e
from sys import getsizeof as size
print(size(()))
print(size(list()))

night quarryBOT
#

@marsh void :white_check_mark: Your eval job has completed with return code 0.

001 | 40
002 | 56
hidden marlin
pure dew
#

hell on earth

marsh void
#

^

proper vault
#

!e

from ctypes import *
(c_void_p*52).from_address(id(int))[16]=cast(CFUNCTYPE(py_object,py_object,py_object,c_void_p)(lambda s,*_:s),c_void_p)
print(5())
night quarryBOT
#

@proper vault :white_check_mark: Your eval job has completed with return code 0.

001 | 5
002 | <string>:3: SyntaxWarning: 'int' object is not callable; perhaps you missed a comma?
proper vault
#

not mine

pure dew
#

!e ```py
from ctypes import *
(c_void_p52).from_address(id(int))[16]=cast(CFUNCTYPE(py_object,py_object,py_object,c_void_p)(lambda s,_:s),c_void_p)
x = 5
print(x())

night quarryBOT
#

@pure dew :white_check_mark: Your eval job has completed with return code 0.

5
pure dew
#

you gotta trick the parser

proper vault
#

I find the warning more appropiate

pure dew
#

OH

#

i didnt notice it still worked

#

thats funny

brazen geyser
#
>>> import ctypes
>>> import sys
>>> string = 'waaaaario'
>>> ctypes.memset(id(string) + sys.getsizeof(string) - len(string) - 1, ord('m'), 1)
2189490438368
>>> string
'maaaaario'
>>> 

mutable strings :P

marsh void
#

@brazen geyser chances it segfaults? heh

brazen geyser
#

it's fairly safe i think

#

maybe dangerous if it's an interned string

snow beacon
#

Just don't put it in a dict key.

brazen geyser
#
>>> def pointer_to(string):
    pointer_type = ctypes.c_char * len(string)
    return pointer_type.from_address(id(string) + sys.getsizeof(string) - len(string) - 1)

>>> pointer_to('a')[0] = b'z'
>>> 'a'
'z'
#

lel

proper vault
#

This is actually pretty useful for avoiding
n= list(str)
n[::2]='5'
''.join(n)
And similar

brazen geyser
#
>>> 'a'+'a'
'aa'
#

????

rugged sparrow
#

it also breaks re

#
>>> 'a'+'a'
'zz'``` ?
brazen geyser
#

what version of python

#

3.7.5 here

rugged sparrow
#

3.8

brazen geyser
#

same result in 3.8

#
>>> 'a' + 'a'
'aa'
>>> 'a'
'z'
>>> 
#

'a'*3 works correctly too

#

🤷‍♂️

sick hound
#

Would it be possible to get a variable which is a pointer to a list member

#

I would think you could if you can get pointers to things

#

But I have no idea how to even start trying it myself

snow beacon
#

You might be able to get an attribute, but a variable would be much harder.

sick hound
#

What's the difference that makes it so

snow beacon
#

Attributes can have getters and setters

sick hound
pure dew
#

ctypes could do it

snow beacon
#

It depends on what you'd do with the variable.

candid forge
#

hey

sick hound
#

@brazen geyser @rugged sparrow i'm guessing it's because sometimes simple operations get optimized ```py

import dis
dis.dis('1 + 1')
1 0 LOAD_CONST 1 (2)
2 RETURN_VALUE```

pure dew
#

ah constant folding

pure dew
#

maybe this is well known, but I've come up with a tiny, fast way to get an array of bits from a byte

vestal solstice
#

dowant

#

it's something with that damn := ?

pure dew
#

nope

#

just bitwise

#
get_bits = lambda b, l=8: ((n, int((b & 2 ** n) > 0)) for n in range(l - 1, -1, -1))
#

returns a generator of (bit_index, bit_value)

#

change l to whatever bitsize you want to parse as

#

although, it does give them backwards fixed

proper vault
#

a much more boring solutionlambda b,l=8: zip(range(l), map(int, bin(b)[2:].zfill(l)[::-1]))

pure dew
#

oh yikes

#

thats string manipulation tho

#

not bad

proper vault
#

I was trying to use an fstring f'{bin(n):0>8.8}', but that does not let you use variables for the format afaik

pure dew
#

it does

#

just gotta nest brackets

proper vault
#

huh, never knew that

pure dew
#

whats this mean

proper vault
#

function call overhead and other python meandering is slower than a string conversion and any operation on it

#
lambda b,l=8: zip(range(l), map(int, f'{bin(b)[2:]:0<{l}.{l}}'))

fstring version. whether to use > or < is questionable

pure dew
#

here i was thinking i discovered something awesome

proper vault
#

it is quite neat, I used similar pieces of code in C and such (at least until I found out about structs and their wondrous uses for accessing specific

pure dew
#

how

proper vault
#

fstrings are fast

pure dew
#

faster than bitwise?

rugged sparrow
#
lambda b,l=8:enumerate(map(int, f'{bin(b)[2:]:0<{l}.{l}}'))```
proper vault
#

ye, that is better

pure dew
#

i have two function calls in mine

#

how is it the slowest

rugged sparrow
#

magic

pure dew
#

that one's 336 nsec

proper vault
#

well, we both call int() (which you do not need btw, bool is a subclass of int

pure dew
#

i'm still using mine because it looks best

proper vault
#

oh wait

pure dew
#

removing int drops it to 328

#

but then i don't get such a nice looking result

rugged sparrow
#

but if it parses the same

proper vault
#

I think your timeit body is not getting evaluated

rugged sparrow
#
i = lambda s:int(i)if(i:=input(s)).isnumeric()else i
``` whats yalls smallest safe integer input
#

ooo you know what would be interesting to golf?

#

an input that converts what you put in into its relevant type

#

so "{'hi':1}" would become {'hi':1}

#

(obv no eval tricks)

snow beacon
#

What types would it need to work with?

rugged sparrow
#

as many as you want

proper vault
#

I would presume every valid python literal

rugged sparrow
#

but id shoot for literals

#

yea

snow beacon
#

lambdas would be hard...

rugged sparrow
#

btw this means to make a string youd acc need to type "a"

proper vault
#

we may want to skip lambdas

#

is that even really a literal

rugged sparrow
#

nah

#

its a func

pure dew
#

i have a number parser i wrote in js

#

it actually parses identifiers too, but thats meh

rugged sparrow
#
i = lambda s='':__import__('json').loads(input(s).replace("'",'"'))``` this is kinda cheating lmao
snow beacon
#

JSON doesn't eval then?

rugged sparrow
#

it doesnt use eval

#

but that also cant parse sets, byte strings, and tuples

snow beacon
#

Ah. Those are important.

rugged sparrow
#

handles the hardest type tho

#

dictionarys

#

as long as its keys/values arent any of those types

snow beacon
#

Another challenge: golf a lisp parser.

proper vault
#

what do you want as the output? cons cells?

snow beacon
#

Some sort of abstract syntax tree, I suppose.

#

Python lists would be fine, if there's a way to support x . y

#

And all the fancy Common Lisp syntax isn't necessary.

#

Basically, a tuple parser with spaces instead of commas, plus \``, ',,` and brackets.

#

That formatting was not how I intended it.

pure dew
#

what is x.y in lisp?

#

not dot product, surely

snow beacon
#

It's a cons operation.

pure dew
#

oh

snow beacon
#

It basically appends to the front of a list, but it works if y isn't a list.

#

Lists in lisp are singly linked, and a cons cell is just a pair, generally containing the first item in the list, and the rest of the list.

pure dew
#

appends x to y or y to x?

#

yea

snow beacon
#

x to y

pure dew
#

i know a little about lisp

#

and i know about the cons structure from haskell

snow beacon
#

I like it better than Python lists, but you can't do as many nifty syntax abominations in Lisps

#

Or Haskell.

pure dew
#

oh yes you can

#

get into monadic and Optic operators

#

wew boi

#

that shits cryptic

snow beacon
#

Is that the syntax, or the standard incomprehensibility of the operations themselves?

pure dew
#

both

snow beacon
#

Lisp, Haskell and Forth all take forms that would normally be syntax, and turn them into ordinary yet labyrinthine functions.

pure dew
#

thats some of the cryptical concepts behind Lens/Optics

#

well i mean

#

you can define your own operators in haskell

#

i really wish i had the discipline to actually sit down and really learn haskell

snow beacon
#

Why have I heard of ekmett...

#

Oh, something to do with continued fractions.

vestal solstice
#

ah yes, enslaved transparent bricks

brazen geyser
#

@pure dew

def get_bits(n, l=8):
    for i in range(l-1, -1, -1):
        yield (n>>i)&1

how bout some bit shifting

pure dew
#

how fast is that

brazen geyser
#
>>> get_bits = lambda b, l=8: ((n, int((b & 2 ** n) > 0)) for n in range(l - 1, -1, -1))
>>> get_bits_2 = lambda b,l=8: zip(range(l), map(int, bin(b)[2:].zfill(l)[::-1]))
>>> get_bits_3 = lambda b,l=8: zip(range(l), map(int, f'{bin(b)[2:]:0<{l}.{l}}'))
>>> get_bits_4 = lambda b,l=8:enumerate(map(int, f'{bin(b)[2:]:0<{l}.{l}}'))
>>> def get_bits_5(n, l=8):
    for i in range(l-1, -1, -1):
        yield (n>>i)&1

        
>>> from timeit import timeit
>>> timeit(lambda: list(get_bits(255)))
5.1405962000000045
>>> timeit(lambda: list(get_bits_2(255)))
2.7823927000000026
>>> timeit(lambda: list(get_bits_3(255)))
2.9149553999999966
>>> timeit(lambda: list(get_bits_4(255)))
2.6694615000000113
>>> timeit(lambda: list(enumerate(get_bits_5(255))))
2.128367200000014
>>> 
south bluff
pure dew
#

tf

dreamy forum
#

!support

rugged sparrow
#
get_bits_5 = lambda n, l=8:((n>>i)&1 for i in range(l-1,-1,-1))```
marsh void
#

thanks

brazen geyser
#

imo it's better to leave out the enumeration

rugged sparrow
#

acc for is faster than map i think

#

and yea prob

brazen geyser
#

that way it can be used with/without based on preference

rugged sparrow
#

fair

marsh void
#
f=lambda n,l=8:enumerate((n>>i)&1for i in range(l-1,-1,-1))``` fixed spaces you have wasted haha
proper vault
#

range(l)[::-1]
range(l-1,-1,-1)

#

and the parentheses around (n>>i) are not needed

rugged sparrow
#
f=lambda n,l=8:(n>>i&1for i in range(l)[::-1])
proper vault
#
f=lambda n,l=8:((l-1-i,n>>i&1)for i in range(l)[::-1])
``` for the enumerated variant
rugged sparrow
#

smart

grave rover
#

what's faster, maps or generators?

proper vault
#

generally, generators AFAIK

grave rover
#

ic

proper vault
#

but it does not make enough of a difference to worry about

brazen geyser
#
>>> data = [None] * 10
>>> timeit(lambda: any(map(bool, data)))
1.0028259000027901
>>> timeit(lambda: any(map(bool, data)))
0.9498011999967275
>>> timeit(lambda: any(bool(i) for i in data))
1.8893212000039057
>>> timeit(lambda: any(bool(i) for i in data))
1.8412518999975873
>>> 
#

genexps operate using python bytecode whereas (i think) map operates on the C level.

#
>>> dis('(bool(i) for i in [])')
  1           0 LOAD_CONST               0 (<code object <genexpr> at 0x0000014912E69030, file "<dis>", line 1>)
              2 LOAD_CONST               1 ('<genexpr>')
              4 MAKE_FUNCTION            0
              6 LOAD_CONST               2 (())
              8 GET_ITER
             10 CALL_FUNCTION            1
             12 RETURN_VALUE

Disassembly of <code object <genexpr> at 0x0000014912E69030, file "<dis>", line 1>:
  1           0 LOAD_FAST                0 (.0)
        >>    2 FOR_ITER                14 (to 18)
              4 STORE_FAST               1 (i)
              6 LOAD_GLOBAL              0 (bool)
              8 LOAD_FAST                1 (i)
             10 CALL_FUNCTION            1
             12 YIELD_VALUE
             14 POP_TOP
             16 JUMP_ABSOLUTE            2
        >>   18 LOAD_CONST               0 (None)
             20 RETURN_VALUE
>>> dis('map(bool, [])')
  1           0 LOAD_NAME                0 (map)
              2 LOAD_NAME                1 (bool)
              4 BUILD_LIST               0
              6 CALL_FUNCTION            2
              8 RETURN_VALUE
>>> 
proper vault
#

I remember map being slower for getting the first element of a tuple in a list

brazen geyser
#

probably lambda overhead

proper vault
#

I tested with operator.itemgetter

brazen geyser
#
>>> first_tuple_elem = lambda t: t[0]
>>> list_of_tuples = [(1, 2, 3)] * 100
>>> timeit(lambda: all(map(lambda t: t[0], list_of_tuples)))
11.444330099999206
>>> timeit(lambda: all(t[0] for t in list_of_tuples))
7.270005300000776
>>> timeit(lambda: all(first_tuple_elem(t) for t in list_of_tuples))
15.800058400003763
>>> 
proper vault
brazen geyser
#

oh forgot to add

#
>>> timeit(lambda: all(map(first_tuple_elem, list_of_tuples)))
9.059378099998867
#

based on this i think we can generalize as follows: if applying a callable, use map. if applying an expression, or if the callable can be reasonably deconstructed as an expression, use genexp

brazen geyser
#

@proper vault

>>> from doublescript.structs import PyTypeObject
>>> class Test:
    pass

>>> struct = PyTypeObject.from_address(id(Test))
>>> struct.tp_mro
(<class '__main__.Test'>, <class 'object'>)
>>> struct.tp_mro = ()
>>> Test.__mro__
()
>>> 
#

:p

#
>>> isinstance(Test(), object)
False
>>> 
#

now it actually works for real this time

#

havent messed with builtins.object

proper vault
#

Nice

brazen geyser
#
>>> struct = PyTypeObject.from_address(id(int))
>>> def int_iter(self):
    yield from range(self)

    
>>> func_type = ctypes.CFUNCTYPE(ctypes.py_object, ctypes.py_object)
>>> func_pointer = func_type(int_iter)
>>> struct.tp_iter = func_pointer
>>> [*12]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> 
#

forbiddenfruit doesnt handle tp_iter yet

brazen geyser
#
>>> PyTypeObject.from_address(id(object)).tp_mro = ()
>>> isinstance(object, type)
True
>>> isinstance(object, object)
False
>>> PyTypeObject.from_address(id(type)).tp_mro = ()
>>> isinstance(type, object)
False
>>> isinstance(type, type)
True
>>> 
#

thats interesting

#

isinstance(..., type) bypasses the mro

#

@tropic night

tropic night
#

yes, as i noted lastly in python-discussion. ... bla bla bla bla... except for type 😄

brazen geyser
#

well ordinarily type would be considered an instance of a class too, by virtue of being an object.

#

just think it's interesting that isinstance(thing, type) willcan return True even if there's nothing in the mro

marsh void
#

@brazen geyser doublescript is again something that messes with C and memory and only works on CPython? heh

marsh void
#

!e
from dis import dis
def ok(string: str) -> None:
print(string), dis(string)
ok('a if a is not None else b')
ok('(a,b)[a is not None]')

night quarryBOT
#

@marsh void :white_check_mark: Your eval job has completed with return code 0.

001 | a if a is not None else b
002 |   1           0 LOAD_NAME                0 (a)
003 |               2 LOAD_CONST               0 (None)
004 |               4 COMPARE_OP               9 (is not)
005 |               6 POP_JUMP_IF_FALSE       12
006 |               8 LOAD_NAME                0 (a)
007 |              10 RETURN_VALUE
008 |         >>   12 LOAD_NAME                1 (b)
009 |              14 RETURN_VALUE
010 | (a,b)[a is not None]
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/asorarocih

thin trout
#

A !dis command could be nice

marsh void
#

gotta ask lemon

#

@thin trout actually, no, it gonna be big

#

the output i mean

thin trout
#

I mean, upload it to the paste service

marsh void
#

oh, I can do that then, haha

snow beacon
#

What I'm seeing from this is that if else is faster.