#esoteric-python
1 messages Β· Page 72 of 1
Also, you might be able to do that trick where you extract values from a string by setting the step and start of a slice
It might add characters though because they're all different lengths
@brisk zenith you actually made something useful in esoteric python :D
jumping here from #help-orange
@distant wave it seems that all you really have to do is add up pascal triangles originating from each point
[0, 0, 0, 0, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0]
[0, 0, 1, 2, 1, 0]
[0, 1, 3, 3, 1]
[1, 4, 6, 4]
[5, 0, 0]
[5, 0]
then just mod 10 the results
the hard part is adding them up correctly
I'm actually not familiar with pascals triangle too well
To build the triangle, start with 1 at the top, then continue placing numbers below it in a triangular pattern. Each number is the numbers directly above it added together.
Ah, so there's a factorial algorithm for it
left=right=0
for i, x in enumerate(list_start):
left += C(len(list_start)-2, i)
right += C(len(list_start)-2, i+1)
where C is n choose k
>>> import ctypes
>>> import functools
>>> def new_method(cls):
... def decorator(func):
... dict = ctypes.py_object.from_address(id(cls.__dict__) + 16).value
... dict[func.__name__] = func
... @functools.wraps(func)
... def wrapper(*args, **kwargs):
... return func(*args, **kwargs)
... return wrapper
... return decorator
>>> @new_method(str)
... def remove_spaces(self):
... return self.replace(' ', '')
...
>>> a = 'so it works kden'
>>> a.remove_spaces()
'soitworkskden'
Sorry for interrupting, I think I made this too; thanks to juanita for + 16 part though
nice
@gentle pagoda -4 characters. Still gives an error if you give it a non-+-[]<>., character, though.
t=d=0;p,m="",[0]*1000
for i in input():j=ord(i)%13;p+=" "*t+'while+m[d]: m[d]+=1 m[d]=ord(input()) m[d]-=1 print(end=chr(m[d])) d-=1 d+=1'.split(" ")[j]+"\n";t-=(j<3)*(j-1)
exec(p)```
was planning on doing something like that but you beat me to it
from math import factorial as f
a = [1, 10, 100, 1000, 10000]
left_set = a[:-1]
right_set = a[1:]
s = len(a)-1
left = sum(f(s)*x/(f(s) - f(i)) for i, x in enumerate(left_set))
right = sum(f(s)*x/(f(s) - f(i)) for i, x in enumerate(right_set))
you'd save on CPU cycles if you did both in the same for loop tho
I'm surprised I even figured out it was a pascal triangle
from math import factorial as f
a = [1, 10, 100, 1000, 10000]
left_set = a[:-1]
right_set = a[1:]
s = len(a)-2
left = sum(f(s)*x/(f(i) * f(s - i)) for i, x in enumerate(left_set))
right = sum(f(s)*x/(f(i) * f(s - i)) for i, x in enumerate(right_set))
Is corrected
Still got the C algorithm wrong
Fixed.
>>> import random
>>> @new_method(list)
... def shuffle(self):
... """Randomly shuffles a list."""
... return random.shuffle(self)
...
>>> test = [*range(10)]
>>> test
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> test.shuffle()
>>> test
[6, 0, 7, 3, 5, 2, 8, 1, 4, 9]
haha nice
from math import*;f=factorial;a=[10**x for x in range(5)];s=len(a)-2;L,R=(sum(f(s)*x/(f(i)*f(s-i))for i, x in enumerate(b))for b in (a[:-1],a[1:]))
ok let's totally obfuscate that
@ripe nest here's where we do all that crazy shit I showed you yesterday btw :P
Ok made a bit shorter
you can replace the difficult loops with *map()
or at least the outer one
Implementation of Function Overloading in Python using a decorator and the inspect and typing modules. - overloads.py
been improving my function overloading a bit
@grave rover is this just a fancy functools.singledispatch?
does singledispatch not do multiple arguments?
@functools.singledispatch```Transform a function into a [single-dispatch](../glossary.html#term-single-dispatch) [generic function](../glossary.html#term-generic-function).
To define a generic function, decorate it with the `@singledispatch` decorator. Note that the dispatch happens on the type of the first argument, create your function accordingly:
```py
>>> from functools import singledispatch
>>> @singledispatch
... def fun(arg, verbose=False):
... if verbose:
... print("Let me just say,", end=" ")
... print(arg)
``` To add overloaded implementations to the function, use the `register()` attribute of the generic function. It is a decorator. For functions annotated with types, the decorator will infer the type of the first argument automatically:... [read more](https://docs.python.org/3.7/library/functools.html#functools.singledispatch)
oh i see
Hey @brisk zenith what if I apply editing object dict to for example logging.Logger? Will it work?
if it has a __dict__ attr, yes
I used a multiple dispatch library by mrocklin in a project once. Is it like that?
Kind of, but I'm soon adding support for Generics to make a difference between Callable[[Dict[KT, VT]], VT] and Callable[[Dict[str, int]], str] for example
But this shit is difficult and nobody else seems to know how
read the C++ overload standard :-)
it's always just most specific type to least
@fallow cairn py def editTuple(tup,index,val): from ctypes import py_object if abs(index) > len(tup)-1: raise IndexError('tuple index out of range') py_object.from_address(id(tup) + 24 + (8 * abs(index))).value = val
Please stop <3
π
What's the id(tup) + 24 + (8 * abs(index))?
oooh better yet
24 is the offset from the start of the tuple var of the first index
and each var is 8 bytes
yea
I'd think a float
hmm
They can get up to 8 bytes normally
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: this type has no size``` hmm
There's an f64 in rust
π€
oh yea, the offset for an objects class is 8
It's like a strange shrodingers box
(if you ever wanted to change it)
I made a horribly slow pi algorithm for laughs and it sort of used 4gb ram from how many ints where used
>>> py_object.from_address(id(1) + 8)
py_object(<class 'int'>)
>>> py_object.from_address(id(1) + 8).value = list
>>> 1
TypeError: unhashable type: 'list'
>>> 1[0]
Segmentation fault (core dumped)``` lmao
Hah
one sec
How to make python unsafe 101
lemme find something i made last week
class myInt(int):
def __eq__(self,*args): return True
def __ne__(self,*args): return True
myInt.__hash__ = int.__hash__
from ctypes import *
py_object.from_address(id(1)+sizeof(c_size_t)).value = myInt
if 1 == 1:
if 1 != 1:
print('unbelievable')``` @fallow cairn
this will print unbelievable
Hah
Looks like it is making ints mutable directly
it makes 1 equal and not equal anything
Cool
i think imma make a module called mutate_everything that just makes everything mutable
thatd be fun
for key, value in __builtins__.__dict__.items():
del(value)
would there be some crazy way to get this to actually work?
oh wow, doing this makes IDLE restart
>>> for key, value in __builtins__.__dict__.items():
__builtins__.__dict__.update({key:''})
=============================== RESTART: Shell ===============================
what?
okay, overwriting issubclass and then making a error restarts the IDLE from what I can see for now
syntax error dont work, but at least NameError does.
if causing an error is what makes it restart, why does it restart even if you add a try except?
it does?
>>> for key, value in __builtins__.__dict__.items():
try:
__builtins__.__dict__.update({key:''})
except:
pass
=============================== RESTART: Shell ===============================
yep
hmmm, it did not with this:
I think it has something with the IDLE using what we overwrite in the error handling, and that makes it crash/restart.
>>> for key, value in __builtins__.__dict__.items():
print(key)
__builtins__.__dict__.update({key:''})
__name__
__doc__
__package__
__loader__
__spec__
__build_class__
__import__
abs
all
any
ascii
bin
breakpoint
callable
chr
compile
delattr
dir
divmod
eval
exec
format
getattr
globals
hasattr
hash
hex
id
input
isinstance
issubclassTraceback (most recent call last):
During handling of the above exception, another exception occurred:
During handling of the above exception, another exception occurred:
During handling of the above exception, another exception occurred:
=============================== RESTART: Shell ===============================```
so issubclass is the last thing we overwrite before it restarts.
or wait it's isinstance since issubclass is what got the error
>>> for key, value in __builtins__.__dict__.items():
if key!='issubClass': __builtins__.__dict__.update({key:''})
=============================== RESTART: Shell ===============================
>>> for key, value in __builtins__.__dict__.items():
if key!='isinstance': __builtins__.__dict__.update({key:''})
=============================== RESTART: Shell ===============================
is it either?
hmmm....
it must be something, but if it's not them. why does it not error sooner?
is it a combination of multiple?
it isn't a combination of issubClass and isinstance
>>> for key, value in __builtins__.__dict__.items():
if key!='isinstance' and key!='issubClass': __builtins__.__dict__.update({key:''})
=============================== RESTART: Shell ===============================
this might be something.
but the code is already running when we overwrite it.
so it cant be that.
could it somehow be package or loader?
heyo what's being discussed here
some weird thing restarting idle.
wait, might it be something with the end of the iter protocol we overwrite , what is the last element.
no, we stop long before the last element.
I have a feeling it must be something with the for loop.
are you trying to figure out which one it is
yes
and why if we can.
running it as a script makes it go longer (maybe to the end) but still error.
the script stopped at print, so that's why it stopped. it overwrote print. hmmm, so we cant use print.
no error when you just run it, must be something with how the idle works.
maybe we overwrite stuff it uses, and if it gets a error in the idle program where it should be no error. it restarts?
it does not use any of the things we overwrite as functions?
maybe it detects we overwrote some critical thing and restarts?
I dont have any ideas anymore.
are there any "invisible" exceptions that dont print anything, since when we got errors after replacing something it restarts. maybe it get's a error but does not print it.
maybe Warning?
Iters have StopIteration errors when you get to the end
The for loop implicitly catches them, iirc
then, why does it restart?
If it raises an exception, it probably checks if it is a valid exception.
That means it checks if it's descended from BaseException.
but, if it's not. it should at least print a error.
If you overwrite the way to do that, it'll keep raising exceptions and checking them.
It'll fail to check them.
Exactly
If raising an exception fails and tries to raise more exceptions, everything naturally breaks
no restart, but something weird
Might be a timing thing, but I doubt it.
Gotta love getting segfaults for no reason
chronos@localhost ~ $ python
Python 3.7.3 (default, Mar 27 2019, 22:11:17)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def makeTuplesMutable():
... from ctypes import py_object,sizeof,c_size_t
... def __setitem__(self,index,val):
... if index < 0 or index > len(self) - 1:
... raise IndexError('tuple index out of range')
... py_object.from_address(id(self)+(sizeof(c_size_t)*3) + (sizeof(c_size_t) * index)).value = val
... py_object.from_address(id(tuple.__dict__) + sizeof(c_size_t) * 2).value['__setitem__'] = __setitem__
...
>>> makeTuplesMutable()
>>> x = (0,)
>>> y = {x:x}
>>> x.__setitem__(0,[])
>>> y[x]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> y
{([],): ([],)}
>>> x[0]
[]
>>> x[0].append(1)
Fatal Python error: GC object already tracked
Current thread 0x00007c5025d92740 (most recent call first):
Aborted (core dumped)``` lol
Wew
type('ClassName',
(
object,
# any other inherited classes
),{
'method':lambda self:print(1)
# any other methods or attributes
}``` @polar plover
hmmm, okay
so that's the same as: py class ClassName(object): def method(self): print(1) ?
yep
cool.
type will return that class
and if you dont care about the classname it can be an empty string
cool, any other tips?
dict compts are useful for when you want to have no imports
no imports?
wow, what is all that
it returns a dict of every initialized class that is based off object that the interpreter uses
or any builtin
wow, just wow.
so if its something like method itll be in there
also, py [ print(1), print(2), print(3), print(4) ] can be py [*map(print,(1,2,3,4)]
good to know.
lists are also useful for running functions in a row
like appendToList = lambda l,i:[l.append(i),l][1]
you should write a blog for this π
is this the "normal" way to import stuff: py ( globals().__setitem__("set_var", lambda k, v: globals().__setitem__(k,v)), set_var("discord", __import__("discord")), )
yea. or you wrap everything in a lambda and do py (lambda random,discord: ... )(**{n:__import__(n) for n in ('random','discord'))
(lambda x:x(x,(lambda x:[[[0]*len(x[i]) for i in range(len(x))],x])((lambda a:(lambda x,y:[[[[x[r].pop(c), x[r].insert(c,'*')] if y[0][r][c] else [x[r].pop(c), x[r].insert(c,y[1][r][c])] for c in range(1,a-1)] for r in range(1,a-1)],x][-1])([[0]*a for x in range(a)],(lambda x:[[[[[(lambda x,y:[y.append(x[1][r][c]), x[1][r].pop(c), x[1][r].insert(c,y[0]+1)])(x,[]) if x[0][l][j] else None for j in range(c-1, c+2)] for l in range(r-1, r+2)] for c in range(1,a-1)] for r in range(1,a-1)], x][-1])((lambda x:[[[[x[0][r].pop(c),x[0][r].insert(c,__import__('random').choice([0,0,0,0,1]))] for c in range(1,a-1)] for r in range(1,a-1)], x][-1])([[[0]*a for x in range(a)] for x in range(2)]))))((lambda i:i if i > 2 and i < 12 else exit())(int(input('Board Size (max 9): '))+2)))))((lambda x,y,p=(lambda x:[print(' ',*range(1,len(x[0])-1),sep=' '),[[[print(r,end='') if c == 0 else [print(' ',end=''),print(['β ','F'][x[0][r][c]], end='') if x[0][r][c] != 2 else print(x[1][r][c], end='')] for c in range(len(x[0])-1)],print()]for r in range(1,len(x[0])-1)],x][-1]),i=(lambda f,i:[f[0][int(i.split(',')[0])].pop(int(i.split(',')[1])),f[0][int(i.split(',')[0])].insert(int(i.split(',')[1]),{'f': 1,'c': 2}[i.split(',')[2].lower()]),[print('You Lose'),exit()] if f[1][int(i.split(',')[0])][int(i.split(',')[1])] == '*' and i.split(',')[2].lower() == 'c' else f][-1]),q=[]:[p(y),q.append(i(y,input('Type Row,Column,[(F)lag or (C)lear]: '))),x(x,q[0]) if not (lambda y,q=[],w=[]:[[[q.append(y[0][r][c] == 1 and y[1][r][c] == '*') for c in range(len(y[0][r]))] for r in range(len(y[0]))],q][-1].count(True) == [[[w.append(y[1][r][c] == '*') for c in range(len(y[1][r]))] for r in range(len(y[1]))],w][-1].count(True))(y) else print('You Flagged All The Bombs!')]))``` @polar plover heres minesweeper
wow, I cant understand this xD
and theres my tryExcept thing
how would I make a async function in 1 line? @rugged sparrow
since discord.py needs to be async.
import asyncio
from time import sleep
from concurrent.futures import ProcessPoolExecutor
async def sleep_async(loop, delay):
# Can set executor to None if a default has been set for loop
await loop.run_in_executor(ProcessPoolExecutor(), sleep, delay)
return 'I slept asynchronously'``` so this lets a syncronous func run asyncronously
@polar plover nevermind, use aioify
hmm this may be tricky
aioify lets us wrap any func in async
but using await is gonna be hard
I am trying to use it, but I get a error: ```py
(
globals().setitem("set_var", lambda k, v: globals().setitem(k,v)),
set_var("discord", import("discord")),
set_var("commands", import("discord.ext.commands")),
set_var("aioify", import("aioify")),
set_var("bot", discord.ext.commands.Bot(command_prefix="!")),
bot.event(aioify.aioify(obj=lambda: print("ready"))),
bot.run(TOKEN)
) py
Traceback (most recent call last):
File "D:/projects/one line bot/main.py", line 9, in <module>
bot.event(aioify.aioify(obj=lambda: print("ready"))),
File "D:\projects\one line bot\venv\lib\site-packages\discord\client.py", line 823, in event
raise TypeError('event registered must be a coroutine function')
TypeError: event registered must be a coroutine function
what object does aioify return?
<function <lambda> at 0x04798B28>
okay, that's good
this still will be tricky
feel free to ping me if you get stuck, im happy to help
in the meantime, im going to sleep
ππΌ
I did it!!!!!!!!!!!
(
globals().__setitem__("set_var", lambda k, v: globals().__setitem__(k,v)),
set_var("discord", __import__("discord")),
set_var("commands", __import__("discord.ext.commands")),
set_var("bot", discord.ext.commands.Bot(command_prefix="!")),
set_var("asyncio", __import__("asyncio")),
bot.command(name="hello")(asyncio.coroutine(lambda ctx: ctx.send("hello world"))),
bot.run(TOKEN)
)```
One-liner bot?
wow
but have you ever made the tiniest ever framework
fyi __import__('discord.ext.commands') probably doesn't return what you think it does (it returns discord, not discord.ext.commands)
anyway https://github.com/csvoss/onelinerizer will probably spoil most of your fun π
@livid seal for some reason I still need to import it, but you are right. I dont need to set it to anything.
yeah, I presume discord.ext.commands isn't imported by any of the parent __init__.py files, so you would indeed have to directly import it
@sick hound I'm actually in way too many Discord guilds
@livid seal yeah but onelining by hand makes for smaller programs
the master has arrived.
yup, definitely. that's what happens when you make something as generic as possible I guess.
the talk is valuable though
I mean
Step 1 convert to bytecode
Step 2 run a bytecode optimizer (WIP)
Step 3 ???
Step 4 Profit !!1!
My bytecode optimizer only optimized variable access and a few stack things rn
@rugged sparrow thanks
Could get rid of a lot of imports with a map()
True
(lambda d,c,i,b={}:[
b.update(b=c.Bot(command_prefix="!"))
b['b'].command(name="hello")(i.coroutine(lambda ctx: ctx.send("hello world"))),
b['b'].run(TOKEN)
])(*map(__import__,['discord','discord.ext.commands','asyncio']))```
@polar plover this should work the same way
oh wait
I dont understand how you get access to bot after just setting it in b?
yah that was me being stupid lol
can happen to the best.
ok now it should work
you also, as of now, dont need to import discord only discord.ext.commands
so it can get shorter still
cool.
now just add more commands π
ππΌ
(lambda c:c(id(tuple.__dict__)+16).value.__setitem__('setitem',lambda self,index,val:[(_ for _ in ()).throw(IndexError,'tuple index out of range') if index < 0 or abs(index) >= len(self) else None,setattr(c(id(self)+24+(8*abs(index))),'value',val)][0]))(__import__('ctypes').py_object.from_address)
``` i built a oneliner that adds ``setitem`` as a instance method on tuples
but it does weird things when i do py x = (1,2,3) x.setitem(0,{}) print(x) # ({94006740150176: <symtable entry top(94006740150176), line 0>}, 2, 3) anyone know why this happends? i assume im writing to some memory thats already used by something
>>> x = (0,)
>>> x.setitem(0,{})
>>> x
({99097711761312: <symtable entry top(99097711761312), line 0>},)
>>> x[0]
Segmentation fault (core dumped)``` huh
it only doesnt like getting a dict initialized in it
wack
reference counting
if there are no references to something it gets deallocated and stuff in it can be overwritten
but if you sneakily add/remove a reference without telling python about it, it gets confused
in this case, the reference to the dictionary is removed when setitem ends
meaning it now has 0 references and is deallocated
@rugged sparrow
probably just random stuff that happens to be in memory
guys i've decided that i'm gonna try to re-do my cpystructs module, but this time make it fully completed with nice code. so far, i'm absolutely loving it, it's so much nicer than my previous implementation. here's a sneak-peak of one of the utilities (just imagine how awful it would be to use a plain ctypes.Structure for this!) ```py
class PyObject(TypedStructure):
if TRACE_REFS:
_ob_next: pointer_to(PyObject)
_ob_prev: pointer_to(PyObject)
ob_refcnt: c_ssize_t
ob_type: pointer_to(PyTypeObject)
the code behind that little bit isn't at all complex, but it makes a massive difference
that's how i can represent the following C struct: ```c
typedef struct _object {
#ifdef Py_TRACE_REFS
struct _object *_ob_next;
struct _object *_ob_prev;
#endif
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;```
hey @grave rover i was looking through the typing module and found this:
!d g typing.overload
@typing.overload```The `@overload` decorator allows describing functions and methods that support multiple different combinations of argument types. A series of `@overload`-decorated definitions must be followed by exactly one non-`@overload`-decorated definition (for the same function/method). The `@overload`-decorated definitions are for the benefit of the type checker only, since they will be overwritten by the non-`@overload`-decorated definition, while the latter is used at runtime but should be ignored by a type checker. At runtime, calling a `@overload`-decorated function directly will raise [`NotImplementedError`](exceptions.html#NotImplementedError "NotImplementedError"). An example of overload that gives a more precise type than can be expressed using a union or a type variable:... [read more](https://docs.python.org/3.7/library/typing.html#typing.overload)
how are you implementing TypedStructure @brisk zenith ?
does it do anything with the type annotations?
yeah, this here: ```py
class PyObject(TypedStructure):
ob_refcnt: c_ssize_t
ob_type: pointer_to(PyTypeObject)
is equivalent to: ```py
class PyObject(Structure):
_fields_ = [
("ob_refcnt", c_ssize_t),
("ob_type", pointer_to(PyTypeObject)
]
it's a small change but it makes a massive difference with readability, especially with some of the structs i'm working with
@brisk zenith TheΒ @overload-decorated definitions are for the benefit of the type checker only, since they will be overwritten by the non-@overload-decorated definition, while the latter is used at runtime but should be ignored by a type checker. At runtime, calling aΒ @overload-decorated function directly will raiseNotImplementedError.
I knew it existed but it was for type hints only
Multiple dispatch (and single dispatch) functions select from different functions based on argument type, rather than having a single implementation that handles every type.
(lambda c:c(id(tuple.__dict__)+16).value.update({'setitem':lambda self,index,val,rec=[]:[(_ for _ in ()).throw(IndexError,'tuple index out of range') if index < 0 or abs(index) >= len(self) else None,rec.append(val),rec.remove(self[index]) if self[index] in rec else None,setattr(c(id(self)+24+(8*abs(index))),'value',val)][0]}))(__import__('ctypes').py_object.from_address)``` add ``setitem`` to tuples
mostly works
you forgot to remove references from the things in the tuple that weren't added with setitem
hence the mostly works
yep
do you know how i could add and remove the refs properly?
ctypes.pythonapi.Py_IncRef and ctypes.pythonapi.Py_DecRef?
I don't know if it counts as esoteric python, but...
The interpreter for this is in python, so.
This is a regex-enhanced assembly language!
This regex creates a match for create_check <NAME> <COMPARISON> <NUMBER>
When it sees this pattern, it injects the code from its body:
And this code happens to be a new macro definition.
So in the endcheck_byte @0 and goto [LOOP] becomes an alias for jmp [LOOP] if @0 < 256
Heh
Hey
I am working on Pandas
Currently I'm reading a excel file using google phoneliib to check if it is a valid number
It's taking around 30s for 1M records can anyone help me with the alternative to give me the similar code for vaex or arrow or anything which is fast
here is the code for pandas
data = pd.read_excel('5lac final.xlsx')
data['Valid'] = data['Mobile'].apply(lambda x: phonenumbers.is_valid_number(phonenumbers.parse(x,)))
and the excel file
To a certain extent making Python code that solves a problem in as little time as possible could be considered esoteric
(The solution is generally just to delegate to some C code.)
Maybe?
Only in some very extreme cases where you'd need to be doing strange stuff
None of this stuff in here you should be using for actual stuff
Hey that's a good way of telling if its om-topic
from mixin import inject, mixin, At, Continue
class Listener:
x = 1
def run(self):
return self.x * 10
@mixin(Listener)
class MixinListener:
@inject(At.HEAD, "run")
def before_run(self):
print("Ran before")
raise Continue
print(Listener().run())
# =>
# Ran before
# 10
```working on a mixin design and the impl is totally evil
if you put a comment at the top of a python file that says coding: unicode-escape, code like this will be valid py \x61 = \'hello'
It can be line 2 as long as line 1 is a comment, so you can keep your shebangs.
(yep, and that)
OverflowError: int too large to convert to float
Things you don't really see in other languages
int(float('inf'))
!e ```python
float(555)
@distant wave Your eval job has completed.
001 | Traceback (most recent call last):
002 | File "<string>", line 5, in <module>
003 | OverflowError: int too large to convert to float
Is there a dynamic-bit float?
well, there's Decimal and Fraction - not really the same thing
there's also http://mpmath.org/
and https://www.sympy.org/en/index.html which uses mpmath underneath
still can't convert to int, rip
Inspired by @timid escarp , has anyone made a prototype inheritance system for python? Using native dictionaries
@sick hound that actually looks like it could be useful
@sonic ginkgo π π
Can you use tuples for the reverse polish notation question?
Also do we have to support negative numbers?
i would guess yes for negative numbers
and yes for tuples
all it says is you can't use lists so
and no imports
i might try it later
i implemented an entire stack class in one line using tuples internally. was good fun
s=();f=lambda e:(e[:e.find(' ')],)+f(e[e.find(' ')+1:])if' 'in e else(e,)
for i in f(input()):
try:s+=float(i),
except:*s,a,b=s;s+=(a+b,a-b,a*b,b and a/b)['+βΓ'.find(i)],
print(s[0])```
should work
it was annoying me for a while because in the example the minus signs aren't consistent
in the first example its a dash
!charinfo -
\u002d : HYPHEN-MINUS - -
\u2212 : MINUS SIGN - β
mine uses the latter
I'm trying to work out how to implement Powershell/Rust range literals in Python e.g. 1..10 for range(1, 10). The best idea I can come up with is overwriting float __getattribute__ to allow for something like 1..ten, which is pretty close. 1..10 won't compile.
Yes .10 won't work because of python limitations
I'll leave the 1..ten implementation as an exercise to the motivated.
We could do one of the language statements
It's a syntax error tho
So not much you can do
I dont think it is helpful but i've implemented it (with modifying cpython)
https://isidentical.github.io/cpython-yeni-operator.html => turkish blog post about how-to
Kendi operatΓΆrΓΌnΓΌzΓΌ oluΕturup cpython codebase'ini tanΔ±yΔ±n.
ofc it isnt runtime hack
import ctypes
float_dict = ctypes.py_object.from_address(id(float.__dict__) + 16).value
float_dict["__getattribute__"] = lambda self, max: range(self, eval(max))
ten = 10
for x in 1..ten:
print(x)
```can someone try this?
Hm, doesn't look like getattr and getattribute are triggered
properties also don't work :(
>>> dir(x)
['__abs__', '__add__', '__bool__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getformat__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__pow__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__round__', '__rpow__', '__rsub__', '__rtruediv__', '__set_format__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', 'as_integer_ratio', 'conjugate', 'fromhex', 'hex', 'imag', 'is_integer', 'real', 'ten']
>>> x.ten
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'float' object has no attribute 'ten'```
firstly, attributes are only based on the name and not any values that happen to be called that, so you're trying to create range(1, 'ten')
and also, you can't just override __getattribute__ in the __dict__, that's not how python works
Fair enough
challenge: golf a program that replaces the value of every single builtin into an empty string
best I could come up with is
a=__builtins__.__dict__
list(map(lambda x:a.update({x:''}),a))
a=__builtins__.__dict__
a.update({x:''for x in a})
a=__builtins__.__dict__
a.update(zip(a,['']*999))
oh yeah good point
don't even need the list
What if we set all the builtins to the same mutable object
oh no
what if we set all the builtins to the same mutable object that was goose typed to work like all the other mutable objects (that it can)
What if we have come up with how to override dunder methods
how do
ctypes,
it's just a bit annoying to figure out where each dunder method is in memory for overwriting
ic
"goose typed"?
Like duck typing, but different, somehow?
Yes. There's an essay in Fluent Python by Alex Martelli (the one credited on wikipedia for the term duck typing) on how duck typing evolved to goose typing
if it looks like a goose, sounds like a goose and acts like a goose, it's a goose?
Almost, but the actual problem with duck typing is that, even when you think something walks or quacks like a duck because it has walk or quack methods, you still don't know if you're dealing with a compatible object
The example he gives in the essay is that an Artist class, a Gunslinger class and a Lottery class can all have draw methods, but they do very different things
but that's why you look at the return type in annotations
So, knowing that they have such a method is not enough to assert that they have interchangeable behavior
But, unless you enforce annotations and check them programmatically, then it's still either a programmer check or a fail-late (when the diverging behavior actually becomes problematic)
Goose typing means that instead of just assuming that an object is compatible and using it, a isinstance check is now okay, as long as you check against an ABC defining a protocol an object needs to implement for your code to run correctly
Obviously, this doesn't mean you actually have to subclass ABCs, since virtual subclassing and subclass hooks come into effect as well, determining whether or not an object implements certain attributes without even having declared them explicitly
e.g.
!e
from collections import abc
class Spam:
def __len__(self):
return 5
s = Spam()
print(isinstance(s, abc.Sized))
@nocturne saddle Your eval job has completed.
True
Wow I just discovered that these are the exact same (though this only works if all arguments are single chars)
example('a','b','c')
example(*'abc')
yep, strings are iterable and * does unpacking
After discovering unpacking I only wished I could use it in more places
same here lmao
# basic python programmer
a = list(range(10))
# more advanced python programmer
a = [*range(10)]
# esoteric python programmer
*a, = range(10)
(lambda c:c(id(tuple.__dict__)+16).value.update({'setitem':lambda self,index,val,rec=[]:[(_ for _ in ()).throw(IndexError,'tuple index out of range') if index < 0 or abs(index) >= len(self) else None,rec.append(val),rec.remove(self[index]) if self[index] in rec else None,setattr(c(id(self)+24+(8*abs(index))),'value',val)][0]}))(__import__('ctypes').py_object.from_address)
``` this makes tuples mutable by adding a ``setitem`` method to them ```py
x = (0,1,2)
x.setitem(0,5)
print(x) #(5,1,2)``` @wind maple
it relies on an implementation instead of language spec so it doesn't really count
fair
yes I meme
Mutability is evil. Tail call everything. No side effects!
Another project to throw in the box: a Python library to raise errors if functional programming standards aren't met.
This is probably a noob question. How does Python evaluate constants?
If I do -~39 it just shows up as a constant 40 in the disassembly
But obviously -~39 is somehow being evaluated beforehand to come to 40
So what's the code of the evaluation?
seems like it's just some optimization done in C
if you look closely it's actually the third constant rather than the first ```py
dis.dis('-~39')
1 0 LOAD_CONST 2 (40)
2 RETURN_VALUE```
I'm wondering what the assembly code of that would be, if that even makes sense to ask
It could be literally a not and a neg instruction
it could be an add instruction
or it could be an inc instruction
or something else maybe
...python "assembly" code or actual x86/x64/whatever assembly code?
like x86
I don't think python is ever compiled into assembly code
it's converted into python bytecode and then that bytecode gets executed
Right, then how is the bytecode executed?
You said it's a C optimisation
So C is compiled of course
well, how is that optimisation routine implemented?
...I don't know
it probably just checks for easy-to-evaluate things like 1 + 1 and puts them into a new constant
I'm trying to find out, if however negligible it may be, what kind of impact doing -~ instead of + has
well if you're doing it on a constant, -~ and +1 are the same when it gets to the actual bytecode
...wait actually
if you do +1, then you will get a constant 1 in the resulting code object
even if you do it on a constant
the co_consts of the result of compiling 5 + 1 is (5, 1, 6)
if instead you do -~5, you get (5, -6, 6)
yes
here's the bytecode of x + 1 vs -~x ```py
dis.dis('x + 1')
1 0 LOAD_NAME 0 (x)
2 LOAD_CONST 0 (1)
4 BINARY_ADD
6 RETURN_VALUE
dis.dis('-~x')
1 0 LOAD_NAME 0 (x)
2 UNARY_INVERT
4 UNARY_NEGATIVE
6 RETURN_VALUE```
oh right
-~ by itself isn't optimized into anything, it just stays as UNARY_INVERT and UNARY_NEGATIVE
but some operations on constants will get optimized into just a single constant ```py
dis.dis('"a" * 10 + "b" * 10')
1 0 LOAD_CONST 5 ('aaaaaaaaaabbbbbbbbbb')
2 RETURN_VALUE```
I was curious how those optimisations happen
the constants from that code object are ('a', 10, 'b', 'aaaaaaaaaa', 'bbbbbbbbbb', 'aaaaaaaaaabbbbbbbbbb')
from that, it seems like the instructions in the code object are scanned in a loop, looking for any operations on constants that can be easily optimized into a single constant
"a" * 10 + "b" * 10 the constants here are 'a', 10 and 'b'
"a" * 10 can become a single constant 'aaaaaaaaaa'
"b" * 10 can become a single constant 'bbbbbbbbbb'
And is that evaluated in C?
'aaaaaaaaaa' + 'bbbbbbbbbb' can become a single constant 'aaaaaaaaaabbbbbbbbbb'
well everything in python is technically evaluated in C because python is written in C
so yes
Hmm right that question doesnt make sense in retrospect
In which source file are the opcodes implemented?
Having trouble finding it
I am pretty sure I've looked at it before
I only found the header file but that's useless
Found it: ceval.c
is it rude to golf a problem someone asked for help with?
i did provide the help, but i also golfed it compulsively, but i feel like posting it would be kind of showing off
well if you're giving them help you probably wanna make sure it's readable for them
if they can't really understand it then... it won't be helpful anyway
oh yeah, as i said i did help; i just golfed it on my own afterwards, but i feel like posting it would have been essentially "btw look how good i am" lol
@spring wedge just send it
you can send it, but you don't need to mention the user you helped or anything. consider it inspiration more than anything :D
what does "to golf a problem" mean ?
oh sorry, missed ping lol
@sick hound "code golfing" is trying to solve a programming challenge in as few characters as possible
anyway this was itpython print("".join(chr(ord(l)+1)for l in input("Word? ")))53 characters
Oh yeah if you just wanna send it here afterwards then thatβs cool
@sick hound the optimization is done in C while converting to python bytecode, as visible in many .pyc files where many operations on constants are evaluated ahead of time
...why are you @ing us...?
I can't remember if I documented that while working on my bytecode optimizer
because you mentioned it initially
If you're interested in bytecode I wrote a library managing it here: https://github.com/martmists/BytePatches
ahh lol, ty @spring wedge
>>> def a():
... global a
... r = 6**6**6
... def b():
... return r
... a.__code__ = b.__code__
... return r
...
>>> a()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in a
ValueError: a() requires a code object with 0 free vars, not 1
>>>
sadness
Out of curiosity, @distant wave what is your goal?
>>> def a():
... r = 6**6**6
... a.__code__ = compile(f"{r}", "<fun.h>", "eval")
... return r
...
>>> a()
behold
a function that modifies itself to return its previously computed result
It saves execution timeβ’ and memory spaceβ’ by caching the precomputed result in place of the original expensive bytecode!
noice
Also never do this >.<
>>> def a():
... print('Doing Expensive Calculations')
... r = 0
... a.__code__ = compile(f"{r}", "<fun.h>", "eval")
... return r
...
>>> a()
Doing Expensive Calculations
0
>>> a()
0
>>> ```
hmm i wonder if i could use this to patch functions after their first call on the fly
Why just the first call?
this just looks like an argument-less functools.lru_cache
and a decorator makes it a lot cleaner ```py
In [7]: def cache_result(func):
...: result = None
...: done = False
...:
...: def wrapper():
...: nonlocal result, done
...:
...: if not done:
...: result = func()
...: done = True
...:
...: return result
...:
...: return wrapper
In [8]: @cache_result
...: def thing():
...: print("doing shenanigans")
...: return "beans"
...:
In [9]: thing()
doing shenanigans
Out[9]: 'beans'
In [10]: thing()
Out[10]: 'beans'
but generally speaking, functools.lru_cache is good for caching results of functions with parameters.
!e ```py
import functools
@functools.lru_cache()
def thing():
print("doing things")
return "beans"
print(thing())
print(thing())```
@brisk zenith Your eval job has completed.
001 | doing things
002 | beans
003 | beans
alternatively (and causing slight possible mem leaks)
>>> def a(r=[]):
... if not r: r.append(6**6**6)
... return r[0]
Is 666 faster than 6**(6*6)?
Should be the same shouldnt it
Lol it changes, interesting
!e
import timeit
def test1():
"""Normal"""
return 6 * 6 * 6
def test2():
"""Bracket"""
return 6 * (6 * 6)
for i in range(3):
print(f"Try No.{i + 1}")
for test in (test1, test2):
print(f"{test.__doc__:<7} -> {timeit.Timer(test).timeit(1000000):.3f}s")
@crystal mica Your eval job has completed.
001 | Try No.1
002 | Normal -> 0.159s
003 | Bracket -> 0.164s
004 | Try No.2
005 | Normal -> 0.160s
006 | Bracket -> 0.161s
007 | Try No.3
008 | Normal -> 0.160s
009 | Bracket -> 0.160s
Huh
And is
6**6**6
Evaluated as 6^(6^6)? Or one after the other?
should be 6 ^ (6 ^ 6)
Sleep is for the week! Good night, 5AM is late(?)
Hahhaha exactly
We its 5 in the morning. And I havent slept all night. So I guess so?
Is it not?
id say so π
@crystal mica it doesn't change at all, that was randomness, they're exactly the same ```py
dis.dis('6 * 6 * 6')
1 0 LOAD_CONST 2 (216)
2 RETURN_VALUE
dis.dis('6 * (6 * 6)')
1 0 LOAD_CONST 2 (216)
2 RETURN_VALUE```
Weird, then how do they have different performance haha
Oooh not multiply, but power
Double ** can you check that @sick hound
Jk itβs multiply in my snippet
Nvm
Now that is pure randomness, imma profile it later
@crystal mica ** also makes the exact same thing
>>> dis.dis('6 ** (6 ** 6)')
1 0 LOAD_CONST 0 (6)
2 LOAD_CONST 1 (46656)
4 BINARY_POWER
6 RETURN_VALUE
>>> dis.dis('6 ** 6 ** 6')
1 0 LOAD_CONST 0 (6)
2 LOAD_CONST 1 (46656)
4 BINARY_POWER
6 RETURN_VALUE```
why is it weird, 6 ** 6 ** 6 is parsed the same as 6 ** (6 ** 6) anyway
just to confuse even more:
6 ** 6 ** 6 == 6 ** (6 ** 6)
True
(6 ** 6) ** 6 == 6 ** (6 ** 6)
False
(6 ** 6) ** 6 == 6 ** (6 * 6)
True```
you're just being intentionally misleading there
6 ** 6 ** 6 and (6 ** 6) ** 6 are completely different things
and the difference between ** and * is like the difference between * and +
well yes, all of those answers are correct
yes
but you've intentionally written them in a way that's confusing
or you've unintentionally written them in a way that's confusing
i asked because it is confusing
wait what question did you ask
was it this: Is 666 faster than 6*(66)?
well at first my phone calculator told me 6 ** 6 ** 6 == 6 ** (6 * 6) so i asked what is faster
wait, did discord mess with it?
6 ** 6 ** 6 == 6 ** (6 * 6)?
then i realised in python its calculated as
6 ** (6 ** 6)
i was just confused because python sees 6 ** 6 ** 6 as 6 ** (6 ** 6) and my calc didnt
since when you type a new symbol it calculates. (at least most do)
my calc saw 6 ** 6 ** 6 as 6 ** (6 * 6).
wait, what
yeah
like you said it evaluated when i was typing
so it saw it as (6 ** 6) ** 6
first raise to the pow of 6 then again on that result
yes, so (6 ** 6) ** 6 not 6 ** (6 * 6). were did you get that from?
@sick hound so yes i posted it like that because it is confusing.
because python sees it like that:
6 ** 6 ** 6 == 6 ** (6 ** 6)
my calc thinks:
6 ** 6 ** 6 == 6 ** (6 * 6)
wait what
how does it get that.
ah yeah
should it not be (6 ** 6) ** 6
because
6 ^ 36 is the same as 6 ^ (6^6)
yes
yeah. thats what my calculator thought i was doing
and python did that to right. as 6 ^ (6^6) (6 ** (6**6))?
uhhh yeah
but because my calculator first evaluated the FIRST power and then the second one on the result of the first ((6 ** 6) ** 6) it messed up
because 6^6^6 is not (6^6)^6
yes
yeah thats it
but in the calculators mind you are doing 6^6 <get result>; <result> ^ 6
yes exactly.
that was my mistake
but i didnt realise i did that so i asked about it
ahhh
ππ»
some more advanced calculators I think lets you just type 6^6^6= and it does it correctly.
yeah my TI can do that but i was just using my phone Β―_(γ)_/Β―
46656
close enough
I am getting Math ERROR on my calculator xD when trying to do 6^6^6
haha
I get a triangle and it says inf
hmm
oh yeah because
my calculator does it the right way
as in 6 ** (6 ** 6)
okay, so it's not syntax. typed in 46656 manually, still error xD
(6 ^ 6) ^ 6 is fine
well its 36306 numbers long long and the first few are 2659
this is fun
!e
class PrintOnModified:
def __set_name__(self, owner, name):
self.name = name
def __set__(self, obj, value):
old_val = obj.__dict__.get(self.name, '<not present>')
print(f'{self.name} modified!! Old value: {old_val}, new value: {value}')
obj.__dict__[self.name] = value
class A:
x = PrintOnModified()
a = A()
a.x = 3
a.x = 4
@sonic ginkgo Your eval job has completed.
001 | x modified!! Old value: <not present>, new value: 3
002 | x modified!! Old value: 3, new value: 4
@sonic ginkgo so is that like setters and getters in other langs?
How does that work?
@grizzled cloak yeah. it's called a "descriptor" and it's the low-level mechanism behind @property, super, and even instance method binding
https://docs.python.org/3/howto/descriptor.html
https://docs.python.org/3/reference/datamodel.html#customizing-attribute-access
https://docs.python.org/3/reference/datamodel.html#implementing-descriptors
when you run a.x, python tries the following, in order:
a.x.__get__(a, type(a))a.__getattribute__('x')a.__getattr__('x')
there are similar hierarchies for setting and deleting
@grizzled cloak __getattribute__ overloads all attribute requests, and __getattr__ only gets called if an attribute is missing.
The naming is... not very clear.
Maybe __get_missingattr__ or __getattr_missing__ would be better?
which one that being called first? and if i want to override get attribute, which dunder do i need to change?
Maybe.
What
What do you mean?
getattribute overloads all attribute requests, and getattr only gets called if an attribute is missing.
Yes, attribute is missing when an object doesn't have the attribute.
!e ```python
"hello".missing_attribute
@formal sandal Your eval job has completed.
001 | Traceback (most recent call last):
002 | File "<string>", line 5, in <module>
003 | AttributeError: 'str' object has no attribute 'missing_attribute'
What does overloads all attr requests?
Mean
It gets called whenever you access it? And the other one only when Attributeerror is raise
d?
Yes.
If you define __getattribute__, all attribute-getting will be redirected there.
But I though __get__ gets called first
Yes, if the attribute has __get__, it will be called first.
So why does __getattribute__ exist if __get__ exists
Look carefully at the code:
class PrintOnModified:
def __set_name__(self, owner, name):
self.name = name
def __set__(self, obj, value):
old_val = obj.__dict__.get(self.name, '<not present>')
print(f'{self.name} modified!! Old value: {old_val}, new value: {value}')
obj.__dict__[self.name] = value
class A:
x = PrintOnModified()
a = A()
a.x = 3
a.x = 4
Sry if im not getting something
Is __set_name__ a actually magic method?
Or just a made up one
__getattribute__ is a method of a class. So, a.hello will result in a.__getattribute__("hello").
__get__ is a method of some other object. If this object gets assigned as the value of an attribute (hello), a.hello will result in a.hello.__get__(a, A).
__set_name__ is a real magic method https://docs.python.org/3/reference/datamodel.html#object.__set_name__
So the get method of hello is called?
If x doesn't exist or the value at x doesn't have __set__, __set__ doesn't get called.
how does it determine if x exists before using __getattribute__ or __getattr__? does it go through __dict__?
It doesn't check if __getattribute__ is defined. Maybe __getattr__ gets triggered on AttributeError?
yes
Challenge: find an input that makes this program halt (without an error)
a=input()
while True:
if all(i in '()=+*/' for i in a):
a=eval(a)
if a!=a:
break
(I haven't been able to do it but I'm pretty sure it's doable)
oh, without an error. there goes that plan xD
Yeah I just realised immediately that you could error it haha
a != a hmmmm, I am no expert, but hmmmmm.
Hint: there's one thing in python that doesn't equal itself
nan
Yep, that's it
Just a heads up, the solution is probably going to be extremely lengthy
okay..... I am never good at this. so not going to be able to xD but can try.
Hint: ||inf/inf==NaN||
Wow, nice job π
Oh wow, you used ** to get it, I didn't even think about that
I probably over complicated it a lot
haha very nice challenge
Something having to do with quiet and signalling NaNs I am guessing?
Normal calculations never produce signalling nans iirc
Nope, there is a way to get a NaN with a normal calculation
@distant wave Your eval job has completed.
[No output]
!e ```python
print((((((()==())+(()==()))((()==())+(()==())+(()==())))**(((()==())+(()==()))((()==())+(()==())+(()==())))(((()==())+(()==())+(()==()))/(()==())))((((()==())+(()==()))((()==())+(()==())+(()==())))(((()==())+(()==()))((()==())+(()==())+(()==())))**(((()==())+(()==())+(()==()))/(()==()))))/(((((()==())+(()==()))((()==())+(()==())+(()==())))(((()==())+(()==()))*((()==())+(()==())+(()==())))(((()==())+(()==())+(()==()))/(()==())))((((()==())+(()==()))((()==())+(()==())+(()==())))(((()==())+(()==()))*((()==())+(()==())+(()==())))(((()==())+(()==())+(()==()))/(()==())))))
@distant wave Your eval job has completed.
nan
Decomposes as
((6**6**(3/1)) * (6**6**(3/1)) / (6**6**(3/1)) * (6**6**(3/1)))
!e print(0*1e309)
@nocturne saddle Your eval job has completed.
nan
@nocturne saddle Your eval job has completed.
False
Although I revealed the clue before I showed the code. hmm, I should work on my delivery
@gilded orchid I know you can get NaNs, but how do you get signalling ones?
wdym?
!e ```python
print(666.0)
@distant wave Your eval job has completed.
001 | Traceback (most recent call last):
002 | File "<string>", line 5, in <module>
003 | OverflowError: (34, 'Result not representable')
From what I can remember of IEEE 754, you have two types of NaNs. The quiet ones are the ones you can get from doing e.g. inf - inf, and the signalling ones are... weird? Quiet NaNs just turn calculations with them into NaN, signalling NaNs can be handled in a variety of ways. I don't know what Python does with them.
I have no idea how to generate signalling NaNs in Python, nor what effect they have, but I was under the impression that they were different from the normal NaNs
I did not know the term, but I've been reading for a bit after you mentioned it earlier
I still don't really get it
There's some discussion here: https://stackoverflow.com/questions/3886988/how-to-distinguish-different-types-of-nan-float-in-python
I'm doing some experiments with the struct module. Looks like float('nan') has a different bit pattern to float('inf')-float('inf')
They differ only in their most significant bit
They differ in the sign bit.
Maybe it's a red herring. edit: yep, they're just + and - nan
From experimentation, it looks like Python only generates nans where the significand only has the most significant bit set. (edit for clarity: not the sign bit)
Wikipedia says those are quiet nans.
Oddly, when I try to convert to and from floats using struct, it keeps setting the most significant bit of the significand anyway. Makes it hard to test, and makes me think maybe Python doesn't support signalling NaNs
that's strange, because i swear pythons float objects are represented by a single C float which i assume does support them. it must be an intentional thing, but i wonder why.
finally finished that
it's a weird stack based language where you can only use bits
the only way of popping is by NANDing, and the only way of pushing is by duplicating
# cpython/Include/floatobject.h : 15
typedef struct {
PyObject_HEAD
double ob_fval;
} PyFloatObject;
``` @brisk zenith it is a C double, but all math is done with conversions first iirc, will investigate
thought so
cant find it sadly :(
what exactly are you looking for?
!e
Sorry, but you may only use this command within #bot-commands.
it's an encrypted message
)([()[)))[]()[]()[]]([(()))])[]])]([)[]()[)(([()
whas this channel
Read the topic
This is a channel where we basically abuse python and do some other stuff such as golfing
dunno if this fits here but i made a decorator that restarts everything if a exception happens
def restart_on_error(func):
def wrapper():
try:
func()
except Exception as e:
print(e)
# closing connections
sys.stdout.flush()
for val in {**globals(), **locals()}.values():
try:
val.close() # try to close everything, may break some stuff that defines close for another purpose
except:
pass
import __main__
appName = __main__.__file__
os.execv(sys.executable, [
'python', "\"{}\"".format(appName)] + sys.argv[1:])
return wrapper
i think this qualifies as gore
So indiscriminate. I love it.
I don't think people would like it too much with that π
Can anyone help with generating the primes up to n in one line?
Well, you'll need a genexp or list comp for that. Do you know how to use those?
I know how to use them, but I can't figure out how to express that with one
You can put multiple functions into one line like this.
>>> (lambda x,f=(lambda x: x % 2 == 0): ([print(f(ele)) for ele in x]))([1,2,3,4])
False
True
False
True
so you'll want to loop over range(2,n+1) and then check if the number is a prime in the if condition
Yes, but how do I check if a number is prime in a single line like that?
How would you do it in muiltiple.
I made a quick example showing only a single number. You'll have to put that into a loop.
>>> (lambda n, is_prime=(lambda n: all(n % num for num in range(2, n))): print(is_prime(n)))(7)
True
>>> (lambda n, is_prime=(lambda n: all(n % num for num in range(2, n))): print(is_prime(n)))(8)
False
>>> (lambda n, is_prime=(lambda n: all(n % num for num in range(2, n))): print(is_prime(n)))(11)
True
all the lambdas
def factors(n):
facts = []
for i in range(1, n+1):
if n % i == 0:
facts.append(i)
return facts
for n in range(11):
if factors(n) == [1, n]:
print(n)
This is how I would generate the primes in multiple lines
Not sure how to compress that though
facts = []
for i in range(1, n+1):
if n % i == 0:
facts.append(i)
return facts``` you could write this with a list comprehension
I way overcomplicated that lol.
yep π
>>> [n for n in range(n) if all(n % num for num in range(2, n))]
[0, 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
This is almost correct. You can probably fix that.
I'd compress that factors function like this:
def factors(n):
print([i for i in range(1, n+1) if n % i == 0])
But that generates the factors of n, not the primes up to n
You can use this list comp you made inside of the next list comp
How? I've not got to grips with the logic of nested list comps yet. Not done that before.
As the part after the if, to check if the number is a prime
Would that list comp be the expression at the start? Like the first i in [i for i in range(1, 10)]
if n % i == 0])
Like this part
What, replace that part with the whole thing?
No, use the entire factors part inside of the if of the second list comp.
[num for num in range if condition]
I'm confused. Sorry.
num is the numbers you are checking for prime.
And condition should be True if they are prime.
So like:
[i for i in range(1, n+1) if [i for i in range(1, n+1) if n % i == 0]]
That's probably horribly wrong.
You probably want to do something with the inner list comp in order to tell that it's prime.
Like comparing the number of elements inside of it.
Well, a number is prime if the factors are 1 and itself, so would I be replacing the if part of the inner list comp with something like:
[i for i in range(1, n+1) if [i for i in range(1, n+1) if {returns a list containing only 1 and n}]]
Sorry if I'm being dumb
Yes, you can check that with ==
What replaces "something" though?
[i for i in range(1, n+1) if [i for i in range(1, n+1) == [1, n]]]
oh, something is [i for i in range(1, n+1) if n % i == 0] my bad
Oh, got you. Let me edit that. Sorry for wasting your time.
You aren't
Like that?
@sick hound https://pypi.org/project/onelinerizer/
Isn't that a bit much?
I mean, it should be easy using exec
but it doesn't cheat by using exec or ;
you only need to divide by ints from 2 to sqrt(n)
@sick hound yeah, it is; but the author says: on the other hand, why not? lol
I did it! Ha! Three nested list comprehensions and I one-lined the primes!
can you one-line the sieve method:
import numpy
def primesfrom2to(n):
""" Input n>=6, Returns a array of primes, 2 <= p < n """
sieve = numpy.ones(n//3 + (n%6==2), dtype=numpy.bool)
for i in range(1,int(n**0.5)//3+1):
if sieve[i]:
k=3*i+1|1
sieve[ k*k//3 ::2*k] = False
sieve[k*(k-2*(i&1)+4)//3::2*k] = False
return numpy.r_[2,3,((3*numpy.nonzero(sieve)[0][1:]+1)|1)]
Not sure about that lol.
we probably can
done py primesfrom2to=lambda n:(lambda sieve:([(lambda k:(sieve.__setitem__(slice(k*k//3,None,2*k),False),sieve.__setitem__(slice(k*(k-2*(i&1)+4)//3,None,2*k),False)))(3*i+1|1)for i in range(1,int(n**0.5)//3+1)if sieve[i]],numpy.r_[2,3,((3*numpy.nonzero(sieve)[0][1:]+1)|1)])[1])(numpy.ones(n//3+(n%6==2),dtype=numpy.bool))
@zealous widget :P
Did you use the onelinerizer library?
no
Nice
we used a text editor
here's the ungolfed version py primesfrom2to = lambda n: (lambda sieve: ( [ (lambda k: ( sieve.__setitem__(slice(k*k//3, None, 2*k), False), sieve.__setitem__(slice(k*(k-2*(i&1)+4)//3, None, 2*k), False) ) )(3*i+1|1) for i in range(1,int(n**0.5)//3+1) if sieve[i] ], numpy.r_[2,3,((3*numpy.nonzero(sieve)[0][1:]+1)|1)] )[1])(numpy.ones(n//3 + (n%6==2), dtype=numpy.bool))
Isn't code golf bad practice?
we aren't in esoteric-python for good practices

Lmao true.
it is for actual code, but this is #esoteric-python and code golf is esoteric
one-lining methods with massive constructions of list comprehensions and lambdas is also bad practice :P
I know lol. I one-lined the primes using 3 for loops.
That's terribly slow.
well, that sieve is pretty optimized, taken from the stack -- but trying to decipher all the arithemetic + boolean methods isn't easy
There's not much in programming that is, unless you're a code guru
figure out what this program prints:
print('hello')```
i optimize a lot of my numpy code when i can
Lmao. I meant outside of "basic" language features.
...isn't the point of numpy basically to optimize code? ._.
yeah, but there are ways to make it even faster, like doing a lot of matrix operations in place instead of naively using in-line operators
a section of my reaction-diffusion implementation:
#React chance is used in both equations
np.multiply(arrays.B, arrays.B, out=arrays.react_chance)
np.multiply(arrays.A, arrays.react_chance, out=arrays.react_chance)
#First Equation done in place
np.multiply(arrays.A, 1 - params.feed, out=arrays.new_A)
np.add(arrays.new_A, arrays.laplace_A, out=arrays.new_A)
np.subtract(arrays.new_A, arrays.react_chance, out=arrays.new_A)
np.add(arrays.new_A, params.feed, out=arrays.new_A)
#Second Equation done in place
np.multiply(arrays.B, 1 - params.kill - params.feed, out=arrays.new_B)
np.add(arrays.new_B, arrays.laplace_B, out=arrays.new_B)
we use out= as often as we can so we aren't initializing new arrays
If I had this Python code, how could I incorporate the primes function into the list_comp2 function so that list_comp2 was independent of the primes function?
def primes(n):
facs = [i for i in range(1, n+1) if n % i == 0]
return facs
def list_comp2():
print("List of primes")
return [i[1] for i in [primes(i) for i in [i for i in range(1, 10)]] if len(i) == 2]
So, instead of writing primes(i) in the list_comp2 function, I have it so that I only need to have the list_comp2 function but list_comp2 is still only one line.
[i[1] for i in [[n for n in range(1, i+1) if i % n == 0] for i in [i for i in range(1, 10)]] if len(i) == 2]
Oh, I see where I made a mistake. I tried that, but I got n is not defined, but I see what I did wrong now.
and because you seem to be laking lambdas haha:
>>> primes=lambda x: [i[1] for i in [[n for n in range(1, i+1) if i % n == 0] for i in [i for i in range(1, x)]] if len(i) == 2]
>>> primes(100)
[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]
>>>```
finding primes in one line ^
no idea if thats the best way to do it
I could use lambdas haha. Trying to grasp list comprehensions though, so I thought I'd use those
I've never used so many list comps at once before. It's kind of hard to track
you can do this:
primes=lambda x: [
i[1] for i in [
[
n for n in range(1, i+1) if i % n == 0
] for i in [i for i in range(1, x)]
] if len(i) == 2
]```
or any other way that makes sense
@sick hound
this was what i came up with in one line:
primes = lambda x: [n for n in range(1, x+1) if n>1 and all(n%i for i in __import__("itertools").islice(__import__("itertools").count(2), int(__import__("math").sqrt(n)-1)))]
p=lambda a:[x for x in range(2,a+1)if all(x%y for y in range(2,int(x**.5)+1))] I think this is an oldie, is it less efficient?
yeah I think
print(timeit.timeit('p(10000)', number=1, globals=globals()))
0.04592208300000067
print(timeit.timeit('f(10000)', number=1, globals=globals()))
6.329603375000005
h m
p is the thing I posted and f is another
try it with the seive
But do the sieve in Haskell. It's way shorter
boo
Love some Haskell
primesfrom2to=lambda n:(lambda sieve:([(lambda k:(sieve.__setitem__(slice(k*k//3,None,2*k),False),sieve.__setitem__(slice(k*(k-2*(i&1)+4)//3,None,2*k),False)))(3*i+1|1)for i in range(1,int(n**0.5)//3+1)if sieve[i]],numpy.r_[2,3,((3*numpy.nonzero(sieve)[0][1:]+1)|1)])[1])(numpy.ones(n//3+(n%6==2),dtype=numpy.bool))
from above
you'll need to import numpy though
include that in the setup for timeit though
salt@ENIAC:~$ python3 /usr/lib/python3.6/timeit.py -n 100 -s 'import numpy' 'primesfrom2to=lambda n:(lambda sieve:([(lambda k:(sieve.__setitem__(slice(k*k//3,None,2*k),False),sieve.__setitem__(slice(k*(k-2*(i&1)+4)//3,None,2*k),False)))(3*i+1|1)for i in range(1,int(n**0.5)//3+1)if sieve[i]],numpy.r_[2,3,((3*numpy.nonzero(sieve)[0][1:]+1)|1)])[1])(numpy.ones(n//3+(n%6==2),dtype=numpy.bool))' 'primesfrom2to(10000)'
100 loops, best of 3: 166 usec per loop
salt@ENIAC:~$ python3 /usr/lib/python3.6/timeit.py -n 100 'primes = lambda x: [n for n in range(1, x+1) if n>1 and all(n%i for i in __import__("itertools").islice(__import__("itertools").count(2), int(__import__("math").sqrt(n)-1)))]' 'primes(10000)'
100 loops, best of 3: 38.3 msec per loop
salt@ENIAC:~$ python3 /usr/lib/python3.6/timeit.py -n 100 'p=lambda a:[x for x in range(2,a+1)if all(x%y for y in range(2,int(x**.5)+1))]' 'p(10000)'
100 loops, best of 3: 29.4 msec per loop
@zealous widget if you take the imports into setup?
Im importing itertools and math alot
yeah if you rewrite the lambdas so we can import itertools outside
but you can see already how fast the sieve is
Yeah
salt@ENIAC:~$ python3 /usr/lib/python3.6/timeit.py -n 10 -s 'import numpy' 'primesfrom2to=lambda n:(lambda sieve:([(lambda k:(sieve.__setitem__(slice(k*k//3,None,2*k),False),sieve.__setitem__(slice(k*(k-2*(i&1)+4)//3,None,2*k),False)))(3*i+1|1)for i in range(1,int(n**0.5)//3+1)if sieve[i]],numpy.r_[2,3,((3*numpy.nonzero(sieve)[0][1:]+1)|1)])[1])(numpy.ones(n//3+(n%6==2),dtype=numpy.bool))' 'primesfrom2to(1000000)'
10 loops, best of 3: 5.16 msec per loop
still faster going up to 1000000
yep
...'primesfrom2to(100000000)'
10 loops, best of 3: 1.19 sec per loop
even tried it for 100 mil
wow
i'd be too afraid to try it with the other methods
what's the error?
No like windows says "not responding"
rip
I waited for a bit but got impatient
that's the difference in complexity of O(n log n loglog n) and O(sqrt(n)/log(n))
we should try to one line the fastest prime search algorithm
Isnt sive already the fastest?
Whats the fastest
https://en.wikipedia.org/wiki/AKS_primality_test --- unfortunately it's fastest for only REALLY large numbers --- no one actually uses the algorithm in practice
The AKS primality test (also known as AgrawalβKayalβSaxena primality test and cyclotomic AKS test) is a deterministic primality-proving algorithm created and published by Manindra Agrawal, Neeraj Kayal, and Nitin Saxena, computer scientists at the Indian Institute of Tech...
nono, sieve isn't polynomial time even
this algorithm was the first polynomial time prime finder
Isn't the AKS test super tough to do for large numbers because you end up with humungous polynomials?
definitely
I would love to do something that requires parallelism.
Either cpu or gpu
Just so I can feel good when it runs 1000x faster on the gpu
we could do the miller test, it depends on riemann's hypothesis to be true though
So do most things.
If someone proved that RH was false, most of mathematics would be down the drain.
nah, inb4 riemann hypothesis is independent of ZF axioms
Aren't most things dependent on ZFC?
Gonna say: "Ofc they are" even though I have no idea what they are
Did you guys study mathematics?
i did, that was my major
No, just computer science and a lot of reading.
What would be really catastrophic would be if someone disproved the Peano axioms
Even basic arithmetic would be fucked.
well, yeah, considering they're arithmetic axioms
That's what I mean, if someone disproved them, we couldn't even add 2 and 2 anymore and expect the answer 4
i doubt that, if there was some inconsistency in peano it would be some very esoteric and nebulous stuff
some convoluted barber's paradox, that they'd add an axiom to fix
and all would be right again
We can't just keep adding new axioms every time something goes wrong. Otherwise, we'd end up with textbooks that just listed all the axioms and said: "memorise these or you'll never amount to anything".
false, we can do whatever we want
We could do that, sure, but who would want us to? We'd just be torturing students.
who cares
if you have a mathematical crisis, you fix it
students be damned
when set theory had it's first hiccup they didn't start from scratch
they added the axiom of regularity and moved on with their lives
Speaking of ZF axioms, what about the axiom of infinity? "There exists some infinite set, but you can't see it."
but you can't see it
wut
Well, I mean we can't write it down.
float("inf")
get rekt
Now add one to it.
Haha
Rekt
and if you really want to blow your mind, look up surreal numbers for a bonifide algebraic field of non-finite numbers
@zealous widget have you thought of paralleising your fluid sim?
definitely not
Why?
Fluid sim?
cause i wouldn't even know where to start and my machine has, like, 2 cores
so whats the point
i don't want to saturate all my cores when running a python program
then my computer dies
4 cores = 4x speed.
If you are not running at 100% on all cores, you are not doing it right
With cores to spare
Does your sim work on a grid env?
What's a fluid?
Water, or anything that obeys the NSE?
No idea haha
Obviously you'll get a different model when you try to model something like syrup than something like water.
fluids are things that take the shape of the container they are in
e.g. water and gases
https://github.com/salt-die/navier-stokes/blob/master/navier_stokes_2D.py syrup and water both use navier stokes
Gas as a fluid is debatable, because you can't see it.
gas is a fluid
gas is modeled by navier-stokes as well
How do you know if it takes that shape if you can't see it taking that shape?
they're all governed by navier stokes
you can see some gases
and you don't need to see with your eyes to observe things
you can't see heat but if someone were to put your hand on a hot plate you could probably tell it's hot
@zealous widget what about non newtonian fluids
do you know how those are modeled
How did we get here in a Python channel? Lol
also I guess this is already very off-topic so I'll move to #ot0-psvmβs-eternal-disapproval
compressible fluids have some other term in there
@zealous widget there is a gpu gems article on navier strokes. I read it some time ago and couldn't wrap my head around it
phew, luckily i don't have that
This is my favourite channel. Really awesome stuff here.
if i only understood half of it :(.
What do you not understand? It's straight up comedy gold.
ugh I'm trying so hard to get "fetch from cache, otherwise run logic to compute value" logic working in two lines
without e.g. repeating the key
the ideal syntax would be something like
with cache_fetch(key) as y:
y = some_logic()
where the body does not run if the key is in the cache
but boy is python making this hard to do
it seems like the least you'll have to do is inspect bytecode but that already is quite fiddly. it's certainly possible, but don't expect to come out of it with sanity left over haha :D
If you're on 3.8, := can do it
yea I was thinking about that